Invoker class 在命令模式中的角色

Role of Invoker class in Command pattern

假设我们在 this way

中实现了命令模式

我对这里调用者的作用有点困惑。我的观点:

  1. 如果我们确实需要历史记录(或命令执行前的任何类型的操作),那么制作此 class 是有意义的。但它打破了单一责任原则,是吗?现在它不仅是一个委托,它还在那里存储历史记录。
  2. 如果我们不需要历史记录,我看不到创建此调用程序的目标,它只是执行委托。是个 唯一的原因只是一个假设,我们将来需要某种逻辑 before/after 命令执行?

还是我遗漏了什么?

您是否阅读了您引用的维基百科文章?

Using an invoker object allows bookkeeping about command executions to be conveniently performed, as well as implementing different modes for commands, which are managed by the invoker object, without the need for the client to be aware of the existence of bookkeeping or modes.

responsibility/purpose不是委托,而是簿记,所以没有违反单一职责原则。

你可能会争辩说,如果 Invoker 同时进行记账 模式管理,它有两个职责,但你可以将 里面的 分开调用者,如果需要的话。

记住,命令模式不关心单一职责。这是一种不同的模式,如果您需要的话,您可以同时应用这两种模式。

在这个特定的设计模式中,Invoker 可选择地记录命令执行

所以我不会太担心保留历史是否有必要,也不担心这是否违反单一责任原则(如果 "bookkeeping" 变得复杂,调用者总是可以将簿记委托给另一个 class).

那么为什么 Invoker 存在呢?

它基本上为您注册您的 Command 操作提供了一个点,该操作对实际问题域的了解尽可能少 - 仅了解如何在 Command 上调用 execute()

这样做的好处包括易于理解的设计模式和减少的耦合(Invoker 不需要了解 Light 的任何信息)。

If we do need history (or any kind of action before command execution), then there is a sense in making this class. But then it breaks Single responsibility principle, yeah? Now it's not only a delegate, it also stores history there.

我完全同意 Andreas 的回答。如果你认为你在执行多个职责,将它们分解成不同的方法。

单一职责原则很好听,但我们不应该过多关注该原则。如果您严格遵循该原则,我敢肯定代码库中充斥着太多小的 classes。我认为软件行业的任何大型项目都没有使用该原则。我们能做的最好的事情是在相同的 class 中针对不同的操作使用不同的方法。

If we don't need history, I don't see a goal of creating this invoker, that simply performs delegating. Is the only reason for it is just a assumption, that we would need some kind of logic before/after command execution in the future?

Command 模式的核心 USP 是 Invoker。它分离了客户端(Sender)和Receiver.

来自oodesign篇文章:

The Client asks for a command to be executed. The Invoker takes the command, encapsulates it and places it in a queue, in case there is something else to do first, and the ConcreteCommand that is in charge of the requested command, sending its result to the Receiver.

我已经在下面的 SE 问题中解释了 Invoker 的作用:

Command Pattern seems needlessly complex (what am I failing to understand?)

来自 http://www.oodesign.com/command-pattern.html:

The example of the meal order at a restaurant is a very good one when trying to explain better how the pattern works: The waiter (Invoker) takes the order from the customer on his pad. The order is then queued for the order cook and gets to the cook (Receiver) where it is processed.