Роль класса Invoker в шаблоне Command

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

Меня немного смущает роль Invoker здесь. С моей точки зрения:

  1. Если нам нужна история (или любое действие перед выполнением команды), то есть смысл сделать этот класс. Но тогда это нарушает принцип единой ответственности, да? Теперь это не только делегат, он еще и историю там хранит.
  2. Если нам не нужна история, я не вижу цели создавать этот инвокер, который просто выполняет делегирование. Является ли единственная причина для этого просто предположением, что нам понадобится какая-то логика до/после выполнения команды в будущем?

Или я что-то упускаю?


person Иван Николайчук    schedule 29.05.2016    source источник


Ответы (4)


Если нам нужна история (или любое действие перед выполнением команды), то есть смысл сделать этот класс. Но тогда это нарушает принцип единой ответственности, да? Теперь это не только делегат, он еще и историю там хранит.

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

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

Если нам не нужна история, я не вижу цели создавать этот инвокер, который просто выполняет делегирование. Является ли единственная причина для этого просто предположением, что нам понадобится какая-то логика до/после выполнения команды в будущем?

Основным УТП шаблона Command является Invoker. Он разделяет клиента ( Sender) и Receiver.

Из статьи oodesign:

Клиент запрашивает команду для выполнения. Invoker принимает команду, инкапсулирует ее и помещает в очередь на случай, если сначала нужно сделать что-то еще, а ConcreteCommand, отвечающая за запрошенную команду, отправляет ее результат Receiver.

Я объяснил роль Invoker в вопросе SE ниже:

Шаблон команды кажется излишне сложным ( что я не понимаю?)

person Ravindra babu    schedule 31.05.2016

Вы читали статью в Википедии, на которую ссылались?

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

Ответственность/цель заключается не в делегировании, а в бухгалтерском учете, поэтому принцип единой ответственности не нарушается.

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

Помните, что шаблон Command не заботится об ответственности Single. Это другой шаблон, и вам решать, применять ли оба, если это то, что вам нужно.

person Andreas    schedule 29.05.2016

В этом конкретном шаблоне проектирования Invoker дополнительно ведет учет выполнения команды.

Поэтому я бы не слишком беспокоился о том, необходимо ли хранить историю и не нарушает ли это принцип единой ответственности (если «бухгалтерия» усложняется, вызывающий всегда может делегировать ее другому классу).

Так почему же Invoker вообще существует?

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

Преимущества такого подхода включают в себя легко понятный шаблон проектирования и меньшую связанность (Invoker не нужно ничего знать о Light).

person vikingsteve    schedule 29.05.2016

с http://www.oodesign.com/command-pattern.html:

Пример заказа еды в ресторане очень хорош, если попытаться лучше объяснить, как работает шаблон: официант (Invoker) принимает заказ от клиента на своем блокноте. Затем заказ ставится в очередь для повара заказа и попадает к повару (получателю), где он обрабатывается.

person Meindert    schedule 27.06.2017