目录
[显示]

1.摘要

Command模式是一种稍微复杂的模式,它将一个请求封装为一个对象,使得调用者-被调用者之间转化为多对多关系。在实现时根据需求不同,可以配合prototype、memento、composite模式使用。

2. 针对问题

假设要设计一个文本编辑器的“打开”按钮,点击之后显示“打开”对话框,之后在窗口中显示文档的内容。我们可以通过按钮类派生一个新类,重写Click处理
逻辑,在Click函数中执行以上的功能。
但这样设计的问题有两个:
1、如果需要多个按钮,那么每种按钮都需要派生一个新类。
2、如果要实现一个“打开”的菜单项,由于菜单不能继承自按钮,代码无法复用。
在这种情况下需要用某种设计模式将“调用者”与“算法逻辑”、“被操作者”解耦。

3. 介绍

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

4. 实现

Command模式的静态图如下:

其中:
Invoker为操作的调用者,例子中的“打开”按钮。
Receiver为被操作对象,例子中的文档窗口。
ConcreteCommand封装了对被操作对象操作逻辑
Command声明Execute函数并将接口提供给调用者。

一个Command模式的顺序图如下:

可以看出,Client负责Command模式的初始化过程:生成Command对象,指定Command对象的操作对象,并且将这个Command保存到Invoker中。

Command实现时可以考虑加入Command的撤销/重做功能,为实现这个功能,Command实例可能需要储存额外的状态信息,包括:
1、操作接收者对象。
2、接收者上执行操作的参数
3、如果操作将改变接收者对象中的某些值,那么这些值也必须存储起来。
4、接收者需要提供某些操作以恢复到之前的状态。
这里可以考虑使用Memento(备忘录)模式储存初始状态。

如果希望支持多次撤销,还需要一个保存已执行Command的栈,如果每次执行Command后Command对象的状态改变,则Stack中需要保存当前Command对象的拷贝,可以使用Prototype模式实现。

对于不能被取消不需要参数的命令可以使用C++模版实现,这时Command只充当转发器的角色。

可以使用Composite模式将几个命令组合为一个新的命令。

5. 特点

1、将调用者→被调用者的模式改为调用者→命令→被调用者,解除了调用者与被调用者之间的耦合。
2、可以支持命令的“重做”与“撤销”功能。
3、可以将多个命令组合成一个新的命令。

6. 相关文章

设计模式总结

7. 参考文章

  1. 《设计模式_可复用面向对象软件的基础》