2010-01-29 7 views
2

Ma compréhension du patron de commande est que vous avez simplement 1 méthode virtuelle 'execute()', et toutes les dépendances qu'une implémentation peut avoir sont placées dans le constructeur ou via l'injection de setter dans l'implémentation (comme discuté here).Motif de commande et conception des paramètres

Cependant, dans la mise en œuvre WPF du motif, je remarquai qu'ils passent un argument générique à l'exécution de la fonction() (expliqué here).

Cela semble être une pollution de l'interface pour moi, ce qui aurait été la motivation pour ajouter un paramètre générique à la fonction execute()?

Répondre

1

Il est pour databinding. Lorsque vous liez la commande à tous les objets dans une liste, par exemple, l'instance en cours est envoyé à la méthode d'exécution afin que vous n'avez pas de garder une trace de l'instance actuelle vous. Cela dit, je ne pense pas que la notion de commande WPF soit une implémentation du modèle de commande, ils partagent simplement la terminologie.

1

La raison derrière ce paramètre est l'isolement entre le créateur de la commande - qui savent quelle commande doit être exécuté, et l'appelant - qui sait quand une commande doivent être exécutés.

Dans certaines commandes, certaines informations nécessaires à l'exécution ne sont pas disponibles pour le créateur. L'appelant remplit le vide en passant un paramètre à exécuter. Un exemple: Le créateur crée une commande qui filtre une liste d'enregistrements en fonction de certains critères. La liste n'est pas disponible sur le site de création, car il existe plusieurs types de listes dans l'application.

L'appelant précisera que la liste doit être filtrée en passant à un paramètre.

+0

Dans votre exemple, je me attends à une interface spécifique pour les commandes de travail sur une liste, qui prend une liste (ou sur l'interface pour une liste) en tant que paramètre, pas une sorte de paramètre générique. – eli

+0

@ eli.work: Je n'ai pas dit que le paramètre doit être générique. Je viens de dire que les données nécessaires à l'exécution ne sont pas toujours disponibles sur le site où l'objet de commande est créé –

+0

Ma question aurait dû être un peu plus claire: c'est la motivation du paramètre générique que je m'interroge. Je vais mettre à jour ma question, et merci pour la réponse! – eli

1

Nous utilisons un modèle de commande légèrement modifié, de sorte qu'en plus de la méthode Execute nous avons deux propriétés Request et Response et nous les paramétrons en utilisant le polymorphisme.

3

Le motif de commande canonique est généralement représenté avec de belles commandes autonomes. En ce sens, toute information nécessaire à la commande est stockée dans l'instance de l'objet Command (généralement via un constructeur paramétré). Cependant, dans certains cas, les paramètres nécessaires à Execute peuvent ne pas être disponibles au moment de la création de la commande (ils ne sont connus qu'au moment de l'exécution). par exemple. Imaginez un SignOutCommand(username). Le nom d'utilisateur est déterminé lorsque l'utilisateur clique sur le bouton SignOut après s'être connecté en premier.

Ainsi, le nom d'utilisateur est transmis en tant que paramètre générique à Command.Execute(); Chaque commande est libre de définir ses entrées et de les diffuser en conséquence. une commande arbitraire peut nécessiter 5 paramètres en tant qu'objet [].

+0

Je vois, mais pourquoi ne pas définir une interface séparée, ou créer une implémentation de commande qui obtient le nom d'utilisateur d'un autre endroit (comme IUserNameGetter)? – eli

+0

@ eli.work C'est un compromis entre la simplicité et l'élégance. Avec un IUserNameGetter, vous devez créer une instance de ce nouveau type et le stocker dans l'objet Command. Avec chaque appel Execute, l'objet de commande enverra à nouveau un message pour récupérer le nom d'utilisateur à partir de l'interface graphique. Plus bavard que de simplement passer dans l'entrée. En outre, avec la restriction WPF d'accès à l'interface graphique à partir du thread qui l'a créée, vous devrez peut-être vérifier le thread et basculer dans votre implicite IUserNameGetter (par exemple si Command.Execute est appelé sur un thread de travail). – Gishu

1

Quel est le problème avec:

public class DeleteCommand : BaseCommand 
{ 
    private Dictionary<string, object> parameters; 

    public DeleteCommand(Dictionary<string, object> parameters) 
    { 
    this.parameters = parameters; 
    } 

    public void Execute() 
    { 
    var person = (Person)parameters["Person"]; 
    var salary = System.Convert.ToDouble(parameters["Salary"]); 

    // etc. 
    } 
} 

Maintenant, si vous avez un contrôleur qui collecte les paramètres que vous pouvez passer ceux à travers vos commandes.

+1

J'ai utilisé une approche similaire dans un cadre d'automatisation de test que j'ai écrit, bien que je transmette la méthode Dictionary à la méthode Execute afin que les objets Action puissent rester sans état et donc être mis en cache. –

Questions connexes