命令模式
提出问题
有时必须向某对象提交请求,但并不知道关于被请求的操作或请求的接收者的任何信息。
问题案例
应用
适用性
- 将“发出请求的对象与“接收与执行这些请求的对象”分离开
- 解耦对象间通过命令对象来沟通,命令对象封装了接受者和一个或一组动作
案例1
当有一个遥控器,它需要控制电灯、车门的开关。它不应该去了解电灯开关的具体细节,只需要控制它打开即可
差的设计:
1
2
3
4if (slot1 ==light)
light.on();
else if (slot1 == hottub)
hottub.jetsOn();命令模式:
- 遥控器是命令的调用者。而启用电灯、开启车门是一项命令。
- 对于遥控器来讲,执行命令即可,至于命令是什么,是可以随意更换的。是开启电灯、车门不需要关心
- 命令对象中绑定着接受者,对于开启电灯来讲,具体传递到哪一个电灯,需要绑定到命令中
以餐厅考虑。
- 顾客点餐,在中间涉及到了:顾客、餐单、服务员、厨师
- 服务员只需要知道这是一份餐单即可,即使餐单更换了也没有影响。服务员不会去关心餐单的信息,只需要接受,然后送给柜台即可。
- 厨师不需要与服务员交互,只需要获取提交过来的餐单即可。
- 即实现解耦合
基础概述
是什么
命令模式:将”请求”封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。
别名:动作、事务
分类
协作
结构
参与者
协作
- 类关系
- 逻辑关系
权衡
分类
结构
效果(优缺)
为什么接受者一定存在, 命令对象不直接执行execute
- 尽量设计“傻瓜”命令对象,只懂得调用一个接受者的一个行为。这样解耦程度最高。
- 可以将接受者作为参数传递给命令。实现多种接受者
实现
通过命令对象实现方法,而调用者通过执行命令对象,从而进行动作
实现步骤
- 定义一个命令对象的接口
- 定义一个实现类,实现接口
- 在方法调用类当中,将接口与实现类绑定
- 需要调用方法时,只需要执行命令接口的方法,则无论是哪一个实现类,都可以实现它的方法。
案例1
####
command接口
1 | /** |
Receiver接收者
1 | /** |
命令对象
1 | /** |
Invoker调用者
1 | /** |
Client
1 | /** |
相关模式
进阶
命令模式的更多特性:队列请求
命令可以将运算块打包,然后将它传来传去。命令对象可以在不同的线程中调用。因此衍生了一些应用:日程安排、线程池、工作队列等。
工作队列:一端添加命令,另一端是线程,从队列当中取出命令,然后调用execute方法
日志请求:某些应用需要我们将过去的动作都记录在日志中,并在系统死机后,重新调用这些动作恢复到之前的状态。通过新增两个方法store和load即可实现