Шаблон команд кажется излишне сложным (что я не понимаю?) - PullRequest
13 голосов
/ 19 мая 2011

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

Зачем тогда нужен Invoker? Какое преимущество дает эта дополнительная косвенность? Мы уже спрятали информацию о получателе за Командой. Какова мотивация, чтобы Команду затем также скрывали от клиента?

Ответы [ 4 ]

4 голосов
/ 10 февраля 2016

Если вы передаете команды другого типа, Invoker полезно. Вы можете использовать один и тот же Invoker для выполнения разных конкретных команд. На другом узле пометка Receiver с ConcreteCommand вместо Invoker позволяет слабую связь. Receiver может изменить имя метода (например, switchOn на swithcOnTV), как в этом примере:

Связанный пост: Использование шаблона Command Design

Чтобы понять цель Invoker, я бы хотел, чтобы вы направили эту статью на случаи использования в ресторане и автосервисе.

Официант (Invoker) принимает заказ от Customer на своем планшете. Затем Order ставится в очередь для повара заказа и попадает к повару (Receiver), где он обрабатывается.

Клиент - Customer. Он посылает свой запрос в Receiver через официанта, который является Invoker. Официант инкапсулирует команду (порядок в данном случае), записывая ее в чек, а затем помещает ее, создавая объект ConcreteCommand, который является самой командой.

Receiver будет поваром, который после завершения работы над всеми заказами, которые были отправлены ему до того, как рассматриваемая команда начнет работу над ним.

Другим заметным аспектом примера является тот факт, что панель для заказов не поддерживает только заказы из меню, поэтому она может поддерживать команды для приготовления множества различных элементов.

3 голосов
/ 20 мая 2011

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

Шаблон называет производителя «клиентом», а потребителя - «Invoker».

Это обратный вызов OO.

Почему тогда необходим Invoker

Насколько я могу судить по всем примерам в Википедии , у призывателя нет определенной формы.Это просто какой-то код, принимающий абстрактную команду.

Мне кажется, что мы могли бы просто остановиться здесь и хранить ссылки на объекты Command

Если это имеет смыслв вашем коде для того, что вызывает команды для принятия или хранения ссылок на абстрактные команды, то вы уже реализовали вызывающий.

Если один бит кода является и производителем, и потребителем, шаблон командыничего не стоит.Это имеет смысл, только когда вы передаете абстрактные команды тому, что хочет их вызвать.

3 голосов
/ 20 мая 2011

Ну, если вы так выразились, это кажется довольно сложным, но часто Приемнику вообще не нужно быть объектом.Это может быть немного больше, чем просто выполняемая функция (как событие).Кроме того, призыватель не должен быть классом.Это просто то, что запускает команду.Это также может быть обработчик события в кнопке.

Even Wikipedia подводит итог нескольких примеров, где этот шаблон используется без фактической реализации полных отдельных классов для invoker и receive.Примером является диалоговое окно мастера, в котором графический интерфейс заполняет объект команды, а кнопка «Готово» вызывает его.Так что этот класс GUI (который у вас есть в любом случае) является и клиентом, и вызывающим.

2 голосов
/ 18 октября 2018

Мы уже спрятали детали получателя за Командой,

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

Таким образом, Client создает экземпляр ConcreteCommand и передает его Invoker, который знает только интерфейс Command.По сути, Клиент выполняет внедрение зависимостей для Invoker.

Также обратите внимание, что существуют различные способы реализации ConcreteCommand (см. https://stackoverflow.com/a/35617012/1371329). Если у ConcreteCommand есть какой-то механизм для динамического обнаружения своего собственного Receiver, тогдавнедрение зависимости может быть ненужным.

...