1.定义
命令模式是最简单和优雅的模式之一,命令模式中的命令(command)指的是一个执行某些特定事情的指令
2.使用场景
命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系
3.命令模式的例子
背景:餐厅点单 不使用命令模式写法
var bindClick = function (button, func) {
button.onclick = func
}
var MenuBar = {
refresh: function(){
console.log( '刷新菜单界面' );
}
};
var SubMenu = {
add: function(){
console.log( '增加子菜单' );
},
del: function(){
console.log( '删除子菜单' );
}
};
bindClick( button1, MenuBar.refresh );
bindClick( button2, SubMenu.add );
bindClick( button3, SubMenu.del );
这种情况的代码如果要实现撤销,排队等操作会比较麻烦,这个时候可以用命令模式来实现 如何使用命令模式来重构代码? 命令模式将过程式的请求调用封装在 command 对象的 execute 方法里,通过封装方法调用,我们可以把运算块包装成形。command 对象可以被四处传递,所以在调用命令的时候,客户(Client)不需要关心事情是如何进行的 命令模式的写法
var setCommand = function (button, command) {
button.onclick = function () {
command.execute();
};
};
var MenuBar = {
refresh: function () {
console.log("刷新菜单界面");
},
};
var RefreshMenuBarCommand = function (receiver) {
return {
execute: function () {
receiver.refresh();
},
};
};
var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar);
var button = document.querySelector("button");
setCommand(button, refreshMenuBarCommand);
4.撤销命令
命令模式的作用不仅是封装运算块,而且可以很方便地给命令对象增加撤销操作。 撤销操作的实现一般是给命令对象增加一个名为unexecude 或者undo 的方法,在该方法里执行execute 的反向操作
- 生成一个历史命令对象,用来存放每一个命令的执行
- 在执行execute时把当前执行的命令中的一些值,放在历史命令对象中
- 在执行撤销操作时,执行unexecude方法,去执行历史命令对象中的值
5.重做
对于一些不容易实现的撤销功能,可以利用一个历史列表堆栈来存放执行过的所有命令,然后再点击重做时,将之前的全部取消,然后依次执行这个历史列表堆栈来实现重做功能
6.宏命令
宏命令是一组命令的集合,通过执行宏命令的方式,可以一次执行一批命令。
场景:想象一下,家里有一个万能遥控器,每天回家的时候,只要按一个特别的按钮,它就会帮我们关上房间门,顺便打开电脑并登录QQ。
var closeDoorCommand = {
execute: function () {
console.log("关门");
},
};
var openPcCommand = {
execute: function () {
console.log("打开电脑");
},
};
var openQQCommand = {
execute: function () {
console.log("打开QQ");
},
};
var MarcoCommand = function () {
return {
commandList: [],
add: function (command) {
this.commandList.push(command);
},
execute: function () {
for (var i = 0, command; (command = this.commandList[i++]); ) {
command.execute();
}
},
};
};
var marcoCommand = MarcoCommand();
marcoCommand.add(closeDoorCommand);
marcoCommand.add(openPcCommand);
marcoCommand.add(openQQCommand);
marcoCommand.execute();
当然我们还可以为宏命令添加撤销功能,跟 macroCommand.execute 类似,当调用macroCommand.undo 方法时,宏命令里包含的所有子命令对象要依次执行各自的undo 操作。 宏命令是命令模式与组合模式的联用产物
7.总结
JavaScript 可以用高阶函数非常方便地实现命令模式。命令模式在JavaScript 语言中是一种隐形的模式