Почему шаблон команд удобен в объектно-ориентированном проектировании?

Я не понимаю, почему шаблон Command удобен в объектно-ориентированном дизайне.

Вместо использования, например, Command Switch который имеет ссылку на класс Lamp, я не могу просто создать абстрактный класс Switchable и вызвать его методы?

Таким образом, в любом случае я разделяю инициатора и получателя, и мне не нужно создавать объект Command для каждого класса получателя.

Ответ 1

Ваш Switchable создает абстракцию между invoker и приемником, но они все еще связаны (у invoker требуется ссылка на приемник). Шаблон Command позволяет создать эту развязку. Вызывающий говорит некоторому промежуточному компоненту "Эй, у меня есть эта команда, которую я хотел бы выполнить", а затем промежуточная вещь может динамически передать этот запрос получателю.

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

Ответ 2

Предположим, вы хотите создать такой список:

  • Включить лампу
  • Установить температуру кондиционера
  • Играть в "Moon River"

Действия и получатели все разные, поэтому вам нужна абстракция, которая отделена от всех из них. Шаблон Command также пригодится, когда вы хотите поддерживать отмену/повтор или подобные вещи.

Ответ 3

Давайте посмотрим на это как: Когда клиент хочет, чтобы получатель выполнил какую-то задачу, клиент имеет два варианта:

  • Call Receiver и попросите его выполнить задачу.
  • Вызовите некоторую третью сторону, которая знает получателя, а третья сторона передаст сообщение получателю.

Первый вариант выглядит лучше, как думать о сценарии, когда в ресторане нет официанта, и вы должны пойти к шеф-повару, чтобы рассказать ему, что вы хотите.

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

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

Ответ 4

You -> Switch -> Light

Здесь переключатель отключает вас и свет. Таким образом, это облегчает включение/выключение света с помощью переключателя. это использование (удобство) при использовании шаблона команды.

Вы - команда Invoker
Switch - командный менеджер
Command - включение/выключение
Свет - Фактический исполнитель

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

Ответ 5

Нет. Вы не можете делать то же самое, что и команда с абстракцией. Фактически каждый раз, когда вы можете выполнять работу шаблона и что-то еще с помощью другого способа, вы можете сделать. Но когда вы меняете Switcher от конкретного до абстрактного, вы должны сделать это для правильного дизайна, независимо от шаблона команды, вы только развязываете клиентский коммутатор с его реализацией и не развязываете коммутатор (т.е. Invoker) из Lamp (т.е. Receiver) потому что, наконец, вы должны иметь ссылку на лампу в бетонах Switcher, которая равна ей в Switcher. Обратите внимание, что лампа является конкретной, и вы не можете изменить ее на абстрактный. Поэтому, когда у вас есть конкретный объект, и вы работаете с ним много времени и много другого атрибута, вы должны использовать Command Pattern для развязки Lamp Switcher, переместив зависимость Switcher to Lamp внутри класса Command и переключив Switcher на промежуточный класс i.e. Command. Кроме того, я думаю, что образец в Википедии очень полезен.

Ответ 6

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

При реализации шаблона Command вы можете иметь структурированную технику хранения пользовательской команды и, таким образом, разрешать такие действия, как undo/redo.

Например, реализация шаблона Command для простого текстового редактора (GOF - глава 2) будет выглядеть так:

введите описание изображения здесь

Сохраняя undoRedoPointer, мы можем выполнить операцию отмены/повтора, увеличивая/уменьшая счетчик каждый раз, когда выполняется команда, не нарушая инкапсуляцию объекта. Это результат объединения команды и шаблона оформления авторских прав.

Ответ 7

Подумайте о каждом объекте "команда" как о живом объекте или задаче, который знает, как выполнять что-то самостоятельно. Ваш invoker - это просто очередь или список, который может

1) удерживайте все эти объекты команд и

2) выполните их в порядке/моде, которые вам нравятся.

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

Ответ 8

Я полагаю, что с помощью Command Pattern несколько инициаторов могут использовать одну и ту же команду. Например, в случае редактора, функция копирования (или алгоритм) должна быть вызвана из команды (ctrl + c) или из меню.

Так что, если бы вы не реализовали шаблон команды, функция copy algo была бы тесно связана с командой ctrl + c, и вам было бы сложно повторно использовать ее, вызывая из меню редактора.

Так это выглядит так...

Ctrl + C действие → CopyCommand → Copy algo Команда копирования меню → CopyCOmmand → Copy algo

Как видно из приведенного выше, источник команды меняется, но назначение остается тем же (скопируйте алгоритм)