Шаблон "команда": Как передать параметры команде?

Мой вопрос связан с шаблоном "команда", где у нас есть следующая абстракция (код C#):

public interface ICommand
{
    void Execute();
}

Давайте примем простое конкретное управление, которое имеет целью удалять объект из нашего приложения. A Person экземпляр, например.

У меня будет a DeletePersonCommand, который реализует ICommand. Для этой команды нужно Person удалить в качестве параметра, для удаления его когда Execute метод называют.

Что лучший способ состоит в том, чтобы справиться с параметризованными командами? Как передать параметры командам, прежде, чем выполнить их?

60
задан Stelios Adamantidis 24 September 2019 в 19:18
поделиться

11 ответов

Необходимо будет связать параметры с объектом команды, или конструктором или инжекцией метода set (или эквивалентный). Возможно, что-то вроде этого:

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

     public void Execute()
     {
        doSomethingWith(personToDelete);
     }
}
61
ответ дан Brad 24 November 2019 в 17:46
поделиться

Передача данных на пути конструктор или работы метода set, но требует, чтобы создатель команды знал данные потребности команды...

идея "контекста" действительно хороша, и я продолжал работать (внутреннее) платформа, которая усилила ее некоторое время назад.

при установке контроллера (компоненты UI, которые взаимодействуют с пользователем, CLI, интерпретирующий пользовательские команды, интерпретацию сервлета входящие параметры и данные сессии, и т.д.) для обеспечения названный доступом к доступным данным команды могут непосредственно попросить данные, которые они хотят.

мне действительно нравится разделение, которое позволяет установка как это. Думайте о разделении на уровни следующим образом:

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

, Если Вы делаете правильно, это, те же команды и модель представления могут использоваться с любым типом пользовательского интерфейса.

Взятие этого шаг вперед, "контроллер" в вышеупомянутом довольно универсален. UI управляет только потребностью знать имя из команды, которую они вызовут - у них (или контроллер) не должно быть знания того, как создать ту команду или в каких данных та команда нуждается. Это - реальное преимущество здесь.

, Например, Вы могли держать название команды для выполнения в Карте. Каждый раз, когда компонент "инициирован" (обычно actionPerformed), контроллер ищет название команды, инстанцирует его, вызовы выполняются, и продвигает его на стеке отмены (если Вы используете один).

21
ответ дан Scott Stanchfield 24 November 2019 в 17:46
поделиться

Существуют некоторые опции:

Вы могли передать параметры свойствами или конструктором.

Другая опция могла быть:

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

И инкапсулируют все параметры команды в объекте значения.

10
ответ дан Steven 24 November 2019 в 17:46
поделиться

В этом случае то, что мы сделали с нашими Объектами команды, должно создать Объект контекста, который является по существу картой. Карта содержит пары значение-имя, где ключи являются константами, и значения являются параметрами, которые используются реализациями Команды. Особенно полезный, если у Вас есть Цепочка Команд, где более поздние команды зависят от контекста, изменяется от более ранних команд.

, Таким образом, фактический метод становится

void execute(Context ctx);
5
ответ дан user12786 24 November 2019 в 17:46
поделиться

Передайте человека при создании объекта команды:

ICommand command = new DeletePersonCommand(person);

так, чтобы при выполнении команды это уже знало все, что это должно знать.

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

   public void Execute()
   {
      RealDelete(person);
   }
}
6
ответ дан jop 24 November 2019 в 17:46
поделиться

В конструкторе и сохраненный как поля.

Вы также захотите в конечном счете сделать свое сериализуемое ICommands для персистентности файла или стека отмены.

4
ответ дан Frank Krueger 24 November 2019 в 17:46
поделиться

На основе шаблона в C#/WPF Интерфейс ICommand (Система. Windows. Вход. ICommand), определяется для взятия объекта в качестве параметра на Выполнении, а также методе CanExecute.

interface ICommand
            {
                bool CanExecute(object parameter);
                void Execute(object parameter);
            }

Это позволяет Вам определять свою команду как статическое общедоступное поле, которое является экземпляром Вашего пользовательского объекта команды, который реализует ICommand.

public static ICommand DeleteCommand = new DeleteCommandInstance();

Таким образом соответствующий объект, в Вашем случае человек, передается в том, когда выполняются, назван. Выполнить метод может тогда бросить объект и назвать Удаление () метод.

public void Execute(object parameter)
            {
                person target = (person)parameter;
                target.Delete();
            } 
3
ответ дан TheZenker 24 November 2019 в 17:46
поделиться

Необходимо создать объект CommandArgs содержать параметры, которые Вы хотите использовать. Введите объект CommandArgs использование конструктора Объекта команды.

1
ответ дан David Robbins 24 November 2019 в 17:46
поделиться

DeletePersonCommand может иметь параметр в своем конструкторе или методах. DeletePersonCommand будет иметь Выполнение (), и в выполнении может проверить атрибут, который будет передан Методом get/методом set ранее вызов Выполнения ().

0
ответ дан Patrick Desjardins 24 November 2019 в 17:46
поделиться

Я добавил бы любые необходимые аргументы конструктору DeletePersonCommand лет. Затем когда Execute() назван, те параметры, переданные в объект во время создания, используются.

0
ответ дан Matt Dillard 24 November 2019 в 17:46
поделиться

Сделайте, чтобы "Человек" реализовал своего рода интерфейс IDeletable, затем заставил команду посещать любой базовый урок или соединить интерфейсом с Вашим использованием объектов. Тем путем можно сделать DeleteCommand, который пытается бросить объект к IDeletable, и если это работает, назовите.Delete

public class DeleteCommand : ICommand
{
   public void Execute(Entity entity)
   {
      IDeletable del = entity as IDeletable;
      if (del != null) del.Delete();
   }
}
-5
ответ дан Joel Martinez 24 November 2019 в 17:46
поделиться