又有点像多态、策略模式
典型场景:菜单操作、编辑器
- setCommond函数
- commond对象
- receiver接收者
- commond.execute执行命令
面向对象的命令模式
传入commond对象,receiver时commond对象的属性 ```typescript var setCommond = function (button, commond) { button.onclick = function() {
} }commond.execute();
var menuBar = { refresh() { console.log(‘刷新菜单目录’); } }
class RefreshMenuBarCommond { constructor(private receiver) {}
execute() { this.receiver.refresh(); } }
var refreshMenuBarCommond = new RefreshMenuBarCommond(menuBar);
setComond(button1, refreshMenuBarCommond);
<a name="sizKA"></a># JavaScript的命令模式receiver作为commond实例的属性 => receiver被封闭在闭包函数环境<br />传入commond实例 => 传入回调函数```javascript// var setCommond// var menuBarvar RefreshMenuBarCommond = function (receiver) {return {execute: () => {receiver.refresh();}}}var refreshMenuBarCommond = RefreshMenuBarCommond(menuBar);setComond(button1, refreshMenuBarCommond);
撤销和重做
撤销一次
undo
class MoveCommond {constructor(private receiver,private pos,private oldPos = null) {}execute() {this.receiver.start('left', this.pos);this.oldPos = this.receiver.dom.getBoundingClientRect().left;}undo() {this.receiver.start('left', this.oldPos);}}
撤销一系列命令
把命令储存在一个历史列表
某些情况无法顺利利用undo让对象回到execute之前状态,如Canvas画图、街头霸王游戏。
先清除画布,然后把刚才执行过的命令全部重新执行一遍。 把用户在键盘的输入都封装成命令,存放到堆栈,播放录像时从头开始执行。
命令队列
问题:用户第二次点击button的时候,此时小球的前一个动画可能尚未结束。
命令对象的生命周期跟初始请求发生的时间无关。
当前commond对象的职责完成后,主动通知队列,此时取出正在队列中等待的第一个命令对象,并且执行它。
如何通知队列?
- 回调函数
- 发布-订阅模式
宏命令
子命令添加进宏命令对象,迭代依次执行它们的execute方法。
智能命令和傻瓜命令
智能命令,没有接收者,直接把行为交给commond对象;
傻瓜命令:有接收者,由接收者统一负责真正执行客户的请求,如上面的 menuBar 。
命令模式和策略模式的区别
策略模式:指向的问题域更小,所有策略对象的目标总是一致的,它们只是达到这个目标的不同手段,它们的内部实现是针对“算法”而言的。
智能命令模式:1. 指向的问题域更广,commond对象解决的目标更具发散性。2. 命令模式还可以完成撤销、排队等功能。
