初探命令模式
代码链接
koonchen/design-patterns/command
要点
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。
这个模式很有意思,直接给一张图先:
假设,我们现在有一个工具箱,其中有一些按钮,我们不知道被请求的操作或请求的接收者的信息。
命令模式通过将请求本身变成一个对象那个来使工具箱对象可向未指定的应用对象提出请求。这里没有标明的 Command
具体子类中有目标接收者 。
比如下面的一个实现:
这个例子就比较明显了,接收者是 document
,这里指定了接收者采取的动作,接收者内部具有执行这个请求的具体信息。
比较特殊的有打开一个新的文档:
它的接收者是 Application
,需要使用的是 Application
的操作。
还有一种是多个命名的执行:
它没有指定接收者,但是每一个指令中都有其具体的接收者。
指令模式的适用性:
- 像上面的
MenuItem
那样,抽象出待执行的动作以参数化某对象。有点类似于 回调 。- 在不同的时刻指定、排序、执行请求。
- 支持取消操作。我们可以在
Command
接口中添加一个Unexecute
操作,取消上一个Execute
调用的影响。- 支持修改日志。当系统崩溃的时候,可以将这些修改重做。
- 用构建在原语操作上的高层操作系统构造一个系统。一个事务封装了对数据的一组变化,我们可以用同一种方式调用所有的事务,同时该模式也易于添加事务以扩展系统。
指令模式的参与者:
- Command — 声明执行操作的接口
- ConcreteCommand — 将一个接收者绑定于一个动作
- Client (Application) — 创建一个具体命名对象并设定它的接收者
- Invoker — 要求改命令执行这个请求
- Receiver — 知道如何实施或执行一个请求相关的操作
指令模式的结构:
协作方式:
Client
创建爱你一个ConcreteCommand
对象并指定它的Receiver
对象- 某
Invoker
对象存储该ConcreteCommand
对象。- 这里的
Invoker
调用Command
对象的execute()
操作来提交一个请求。- 而
ConcreteCommand
通过Receiver
的操作执行这个请求。
效果:
- 接收者对象,它真正执行处理该请求的各操作
- 接收者上执行操作的参数
- 如果处理请求的操作会改变接收者对象的某些值,那么这些值应该先存储起来。
- 避免取消操作过程中的错误积累
实现
Java 实现
1 | class Invoker { |
相关模式:
Memento 模式可被保持某个状态,命令用这一状态来消除它的效果