![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102242196-1923143952.png)
命令模式
将“请求”封装成对象(命令对象),以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
使用场景
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统需要在不同的时间指定请求、将请求排队和执行请求。
- 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
- 系统需要将一组操作组合在一起,即支持宏命令。
基本类图
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102243571-1612840870.jpg)
示例:具体需求
现在有如下请求:希望能通过遥控器实现:开灯、关灯、开门、关门等;
开灯、关灯的具体执行是在Light类中,开门、关门的具体执行是在Door类中;
现在希望把开关灯、开关门的请求封装到Command对象中。
类图及目录结构
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102244727-1872493869.gif)
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102245024-1263809754.png)
Command接口
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102245617-530766372.png)
Receiver
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102245977-213758736.png)
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102246711-537167377.png)
ConcreteCommand:封装具体的请求
共有4个Command:
- 开灯请求;
- 开门请求;
- 无任何操作的请求;
- 宏请求:可以包含多个Commands
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102247117-1159039430.png)
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102247617-2023563760.png)
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102248117-2133783559.png)
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102248633-622244072.png)
Invoke 调用者
个人理解:
之所以需要通过调用者来执行Command,而不是直接command.execute(),主要有如下好处:
- 通过client调用时,比较统一;
- 可以在Invoke中封装undo以及redo命令;
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102249102-1608868878.png)
client 程序测试
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102249696-1176993521.png)
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102250258-557355322.png)
高级用法
![](https://images2015.cnblogs.com/blog/731047/201606/731047-20160603102251617-1739389071.jpg)