71 votes

Modèle de commande: Comment passer des paramètres à une commande?

Ma question est liée au modèle de commande, où nous avons la suite de l'abstraction (code C#) :

public interface ICommand
{
    void Execute();
}

Prenons un simple béton de commande, qui vise à supprimer une entité à partir de notre application. Un Person , par exemple.

Je vais avoir un DeletePersonCommand, qui implémente ICommand. Cette commande nécessite l' Person pour supprimer un paramètre, afin de le supprimer lorsqu' Execute méthode est appelée.

Quelle est la meilleure façon de gérer les commandes paramétrées ? Comment passer des paramètres aux commandes, avant de les exécuter ?

73voto

Blair Conrad Points 56195

Vous devrez associer les paramètres à l'objet de commande, par injection de constructeur ou de setter (ou équivalent). Peut-être quelque chose comme ça:

 public classs DeletePersonCommand: ICommand
{
     private Person personToDelete;
     public DeletePersonCommand(Person personToDelete)
     {
         this.personToDelete = personToDelete;
     }

     public void Execute()
     {
        doSomethingWith(personToDelete);
     }
}
 

23voto

Scott Stanchfield Points 15863

La transmission des données via un constructeur ou un setter fonctionne, mais exige que le créateur de la commande pour connaître les données de la commande...

Le "contexte" l'idée est vraiment bonne, et je travaillais sur (interne) cadre que l'effet de levier il y a quelques temps.

Si vous avez configuré votre contrôleur (composants de l'INTERFACE utilisateur qui interagissent avec l'utilisateur de la CLI interpréter les commandes de l'utilisateur, servlet interprétation des paramètres entrants et les données de session, etc) afin de fournir l'accès nommé les données disponibles, les commandes peuvent directement demander les données qu'ils veulent.

J'aime vraiment la séparation d'une telle configuration permet. Pensez à la superposition comme suit:

User Interface (GUI controls, CLI, etc)
    |
[syncs with/gets data]
    V
Controller / Presentation Model
    |                    ^
[executes]               |
    V                    |
Commands --------> [gets data by name]
    |
[updates]
    V
Domain Model

Si vous le faites, ce "droit", les mêmes commandes et de la présentation du modèle peut être utilisé avec n'importe quel type d'interface utilisateur.

En outre, le "contrôleur" dans le ci-dessus est assez générique. Les contrôles de l'INTERFACE utilisateur a seulement besoin de connaître le nom de la commande ils invoquent-ils (ou le contrôleur) n'ont pas besoin d'aucune connaissance de la façon de créer de la commande ou de ce que les données de commande de besoins. C'est l'avantage réel ici.

Par exemple, vous pouvez conserver le nom de la commande à exécuter dans une Carte. Chaque fois que le composant est "déclenché" (généralement un actionPerformed), le contrôleur de recherche le nom de la commande, instancie, appels exécuter, et le pousse sur la pile d'annulation (si vous en utilisez un).

12voto

Juanma Points 2648

Il y a quelques options:

Vous pouvez passer des paramètres par propriétés ou par constructeur.

Une autre option pourrait être:

 interface ICommand<T>
{
    void Execute(T args);
}
 

Et encapsulez tous les paramètres de commande dans un objet de valeur.

8voto

bloparod Points 808

Ma mise en œuvre serait la suivante (utilisant la commande ICommand proposée par Juanma):

 public class DeletePersonCommand: ICommand<Person>
{
    public DeletePersonCommand(IPersonService personService)
    {  
        this.personService = personService;
    }

    public void Execute(Person person)
    {
        this.personService.DeletePerson(person);
    }
}
 

IPersonService pourrait être un IPersonRepository, cela dépend de la "couche" de votre commande.

6voto

jop Points 31978

Transmettez la personne lorsque vous créez l'objet de commande:

 ICommand command = new DeletePersonCommand(person);
 

de sorte que lorsque vous exécutez la commande, il sait déjà tout ce qu'il doit savoir.

 class DeletePersonCommand : ICommand
{
   private Person person;
   public DeletePersonCommand(Person person)
   {
      this.person = person;
   }

   public void Execute()
   {
      RealDelete(person);
   }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X