命令模式 - 目的?
读完后: http://sourcemaking.com/design_patterns/command
我仍然不太明白为什么我们需要这个。
After reading this: http://sourcemaking.com/design_patterns/command
I still don't quite understand why we need this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这个想法是,如果命令被封装为对象,那么这些命令可以被捕获、存储、排队、重放等。
它还使命令更容易知道如何撤消自身(即执行相反的操作),这样如果命令被处理后,可以将其存储在列表中,然后以相反的顺序“撤消”以恢复命令完成之前的状态。
它还将命令发送者与接收者分离。这可以允许多个事物生成相同的命令(例如菜单项和按钮),并且将以相同的方式处理它们。
The idea is that if commands are encapsulated as objects then those commands can be captured, stored, queued, replayed etc.
It also makes it easier for the command to know how to undo themselves (ie perform the reverse operation) so that then if a command is processed it can be stored in a list and then 'undone' in the reverse order to restore the state before the commands were done.
Also it decouples the sender of the command from the receiver. This can allow multiple things to generate the same command (a menu item and a button for example) and they will be handled in the same way.
这是封装异步操作并将其参数和上下文保存在一个位置的好方法。
例如,HTTP 请求:您通过套接字发送请求,然后等待响应到达。如果您的应用程序是网络浏览器,那么您不希望在请求完成之前阻塞,而是继续前进。如果响应到达,您必须在停止的上下文中继续,例如读取数据并将其放入正确的位置(例如将下载的图像数据放在某处以供稍后渲染)。如果您有一个大客户端类触发多个异步操作,那么将响应与其所属的上下文相匹配可能会变得很棘手。响应可能以任意顺序到达。哪个响应属于什么?又应该对响应做什么?如何处理可能出现的错误?如果您将这些请求封装在命令中,并让命令只接收自己的响应,它们就会更好地知道如何从那里继续并处理响应。如果您有请求/响应序列,则跟踪序列的状态也会更容易。可以将命令分组为复合命令(复合模式)。
客户端将命令所需的所有内容传递给命令,并等待命令完成,报告成功或错误。
另一个很大的优点是使用多线程时:如果操作所需的所有数据都封装在命令对象中,则可以轻松地将命令移动到另一个线程并在那里执行,而无需通常的锁定在线程之间共享对象时会遇到令人头痛的问题。创建命令,将其需要的所有内容传递给它(复制,而不是通过引用),传递给其他线程,仅在接收结果时同步,完成。
It's a good way to encapsulate asynchronous operations and keep their parameters and context in one place.
E.g. a HTTP request: You send a request over a socket, and wait for the response to arrive. If your application is e.g. a web browser, you don't want to block until the request is done but move on. If the response arrives, you have to continue in the context were you stopped, e.g. reading the data and putting it into the right place (e.g. put the downloaded image data somewhere for later rendering). To match the response to the context it belongs to can become tricky if you have one big client class firing off multiple asynchronous operations. Responses might arrive in arbitrary order. Which response belongs to what? What again should be done with the response? How to handle possible errors? If you have those requests encapsulated in commands and let the commands only receive their own response, they'll know better how to continue from there and handle the response. If you have sequences of requests/responses, it's also much easier to keep track of the sequence's state. One can group commands to composite commands (composite pattern).
The client passes everything needed to the command, and waits until the command finishes, reporting back either success or error.
Another big advantage is when using multi-threading: if all data needed for the operation is encapsulated in the command object, it's easy to move the command to another thread and have it executed there, without the usual locking headaches you get when sharing objects among threads. Create command, pass everything it needs to it (copy, not by reference), pass to other thread, synchronize only when receiving the result, done.
命令模式将知道如何执行某些工作的代码与知道何时需要完成某些工作以及使用哪些参数的代码分开。
最明显的例子是一个按钮,它知道您何时单击它,但不知道此时要做什么工作。命令模式允许您将 do-some-work 对象传递给按钮,该按钮在单击时调用该对象。
The command pattern separates the code that knows how to do some work from the code that knows when it needs to be done, and with what parameters.
The most obvious case is a button that knows when you click it, but doesn't know what work to do at that moment. The command pattern lets you pass a do-some-work object to the button, which invokes the object when it is clicked.
基本上,命令模式是一种在 Java(或 C#)中部分实现“函数即对象”的方法。
由于您不能只创建一个函数(或方法)并对其执行任何您想要的操作,例如将其作为参数传递给其他函数或将其保留在变量中以供以后执行,因此这是执行此操作的解决方法
execute
方法)。execute
方法。Basically, the Command pattern is a way to partially achieve "Function as object" in Java (or C#).
Since you can't just create a function (or method) and do whatever you want with it like pass it as a parameter to some other function or keep it in a variable for later execution, this is the workaround to do that:
execute
method).execute
method.它描述了问题的解决方案。主要是,我们想要发出命令,并且不想在 8 个类中定义 30 个方法来实现此目的。通过使用模式提及,我们发出一个 Command 对象,该对象可以自由地忽略它,或以某种方式对其进行操作。 Command 对象的复杂性是实现定义的,但这是告诉对象“嘿,执行此操作”的好方法。
此外,因为我们已将其封装在一个对象中,所以我们可以进一步对命令进行排队,按照我们希望的时间间隔分派它们并还原它们(当然,前提是您发送命令的对象可以“撤消”命令以及'做它')。
因此,想象一下一个绘图包,它允许您将形状添加到画布上。每次用户执行此操作时,都可以发出命令:
等等。假定的
Line
和Circle
派生自通用的Command
基类。我们的渲染器可以使用此画布集合作为渲染方式,而取消操作只是删除最后执行的命令。通过在单独的集合中跟踪用户取消执行的操作,我们还可以重做。
It describes a solution to a problem. Mainly, that we want to issue commands and don't want to define 30 methods over 8 classes to achieve this. By using the pattern mention, we issue a
Command
object and the object is free to ignore it, or act on it in someway. The complexity of theCommand
object is implementation-defined, but this is a nice way to tell objects "hey, do this".Additionally, because we have encapsulated this in an object we can go further and queue commands, dispatch them at intervals we wish and also revert them (provided of course, that the object you send the command to can 'undo' a Command as well as 'do it').
So, imagine a drawing package that allows you to add shapes to a canvas. Each time the user does this, a command can be issued:
and so on. This assumed
Line
andCircle
are derived from a commonCommand
base class.Our renderer can use this canvas collection as a way of rendering and un-doing is simply a case of removing the last performed command. By tracking what the user un-does in a separate collection, we can also redo.