命令模式似乎不必要地复杂(我不明白什么?)
我已经阅读了命令模式,我想我错过了一些东西。 Command 对象的存在是为了抽象出 Receiver 对象的细节。在我看来,我们可以简单地停在这里,并保存对 Command 对象的引用,以便在适当的时间执行适当的方法。
那么,为什么需要调用者呢?这个额外的间接提供了什么优势?我们已经将接收者的详细信息隐藏在命令后面,那么命令对客户端也隐藏的动机是什么?
I've read up on the Command Pattern, and I think I'm missing something. The Command object exists to abstract away the details of the Receiver object. It seems to me that we could simply stop here, and hold references to Command objects to execute the appropriate method at the appropriate time.
Why, then, is the Invoker needed? What advantage does this additional indirection provide? We've already hidden the details of the Receiver behind the Command, what's the motivation for the Command to then be hidden from the client as well?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,如果你这么说,它看起来相当复杂,但通常 Receiver 根本不需要是一个对象。它只不过是一个被执行的函数(作为一个事件)。此外,调用者不需要是一个类。它只是触发命令的东西。这也可以是按钮中的事件处理程序。
甚至 Wikipedia 也总结了几个使用此模式的示例,而无需实际实现完整的单独类对于调用者和接收者。一个示例是向导对话框,其中 GUI 填充命令对象,并且“完成”按钮触发它。因此 GUI 类(无论如何你都有)既是客户端又是调用者。
Well, if you put it that way, it seems quite complex, but often a Receiver doesn't need to be an object at all. It can be little more than just a function that is executed (as an event). Also, the invoker doesn't need to be a class. It is just the thing that triggers the command. This also can be an event handler in a button.
Even Wikipedia sums up a couple of examples where this pattern is used without actually having to implement complete separate classes for invoker and receiver. An example is a wizard dialog, where the GUI populates the command object, and a Finish button triggers it. So that GUI class (that you have anyway) is both the client and the invoker.
如果您传递不同类型的命令,
Invoker
很有用。您可以使用相同的 Invoker 来执行不同的具体命令。在不同的节点上,使用ConcreteCommand
而不是Invoker
标记Receiver
可以实现松散耦合。接收方
可以更改方法的名称(例如 switchOn 为 swithcOnTV),如下例所示:相关文章:使用命令设计模式
要了解
Invoker
的用途,我希望您参考此使用命令设计模式 oodesign.com/command-pattern.html" rel="nofollow noreferrer">关于餐厅和餐厅的文章汽车服务中心用例。服务员(
Invoker
)在他的平板电脑上接受顾客
的订单。然后,Order
将排队等待订单厨师,并到达厨师(接收者
)进行处理。客户是
客户
。他通过服务员(即调用者
)将请求发送给接收者
。服务员通过将命令(在本例中为订单)写在支票上来封装命令,然后将其放置,创建ConcreteCommand
对象,该对象就是命令本身。接收者将是厨师,在完成相关命令之前发送给他的所有订单后,开始处理该订单。
该示例的另一个值得注意的方面是,订单垫不仅支持菜单中的订单,因此它可以支持烹饪许多不同项目的命令。
If you are passing different type of commands,
Invoker
is useful. You can use same Invoker for execution of different concrete commands. On a different node, taggingReceiver
withConcreteCommand
instead ofInvoker
allows loose coupling. TheReceiver
may change the name of the method (e.g. switchOn to swithcOnTV) as in this example:Related post: Using Command Design pattern
To understand the purpose of
Invoker
,I would like you to refer this article on Restaurant & Car Service centre use cases.The waiter (
Invoker
) takes the order from theCustomer
on his pad. TheOrder
is then queued for the order cook and gets to the cook (Receiver
) where it is processed.The Client is the
Customer
. He sends his request to theReceiver
through the waiter, who is theInvoker
. The waiter encapsulates the command (the order in this case) by writing it on the check and then places it, creating theConcreteCommand
object which is the command itself.The
Receiver
will be the cook that, after completing work on all the orders that were sent to him before the command in question, starts work on it.Another noticeable aspect of the example is the fact that the pad for the orders does not support only orders from the menu, so it can support commands to cook many different items.
据我所知,该模式的重点是拥有某种命令生产者和某种命令消费者,但允许生产者创建或修改命令而不需要消费者改变。
该模式将生产者称为“客户端”,将消费者称为“调用者”。
这是一个 OO 回调。
据我所知,维基百科上的所有示例,调用者没有明确的形式。它只是一些接受抽象命令的代码。
如果在您的代码中调用命令以接受或保存对抽象命令的引用是有意义的,那么您已经实现了调用程序。
如果一位代码既是生产者又是消费者,那么命令模式就毫无价值。仅当您将抽象命令传递给想要调用它们的对象时,这才有意义。
From what I can tell, the whole point of the pattern is to have some sort of command producer and some sort of command consumer, but allow the producer to create or modify commands without the consumer changing.
The pattern calls the producer the "Client" and the consumer the "Invoker".
It is an OO callback.
As far as I can tell from all the examples on Wikipedia, the invoker doesn't have a definite form. It is simply some code that accepts an abstract command.
If it makes sense in your code for the thing that invokes commands to accept or hold references to abstract commands, then you've already implemented the invoker.
If one bit of code is both the producer and the consumer, the command pattern is worthless. It is only worthwhile when you are passing abstract commands to something that wants to invoke them.
这是完全正确的,但是谁隐藏了这些详细信息以及它们向谁隐藏?
答案是,无论谁实例化命令实现,都在进行隐藏,而无论谁调用命令抽象,都将被隐藏。显然,这两个动作由一个对象执行是没有意义的,就像你无法向自己隐藏某些东西一样。
因此,
Client
实例化一个ConcreteCommand
并将其传递给Invoker
,后者只知道Command
接口。实际上,客户端为调用者执行依赖注入。另请注意,实现 ConcreteCommand 的方法有多种(请参阅 https://stackoverflow.com/a/35617012/1371329) 。如果ConcreteCommand有某种机制来动态发现它自己的接收者,那么依赖注入可能是不必要的。
That's exactly right, but who is hiding those details and who are they hidden from?
The answer is that whomever instantiates the Command implementation is doing the hiding, and whomever invokes the Command abstraction is hidden from. Clearly it makes no sense for both of those actions to be performed by one object, any more than you can hide something from yourself.
Thus, the
Client
instantiates aConcreteCommand
and passes it to theInvoker
, who is only aware of theCommand
interface. In effect, the Client performs dependency injection for the Invoker.Also note there are different ways to implement a ConcreteCommand (see https://stackoverflow.com/a/35617012/1371329). If the ConcreteCommand has some mechanism to dynamically discover its own Receiver, then dependency injection may be unnecessary.