定义
总结:
命令模式把行为封装为对象,命令对象将发出请求的对象和实际处理请求的对象区分开来,从而实现松耦合设计。这些请求被称为事件,处理这些请求的代码被称为事件处理器。
现假设你正在开发一个支持剪切、复制、粘贴等鼠标操作的应用程序。应用中能以不同的方式触发这些操作,例如一些菜单操作或者键盘的快捷键。
Command对象可以集中对每一个操作的处理。每个操作对应一个命令。所以剪切、复制、粘贴操作分别对应一个命令。
因为命令集中处理,所以经常出现在一些需要撤销的应用中。
例子:
在我们的例子中,计算器有四种操作,加减乘除,每种操作被封装成一个单独的Command对象。
计算器有个命令堆栈,每种命令执行后被压入该堆栈中,撤销操作时,只需要弹出堆栈,执行弹出的命令对象的相反操作的方法。
JS的函数对象(以及回调)是天然的命令对象,他们能够像对象一样传递,实际上,他们是本质上也是对象。
将请求封装为对象,从而客户端可以接收不同的请求对象、队列或日志请求作为参数,并支持可撤销的操作。
总结:
命令模式把行为封装为对象,命令对象将发出请求的对象和实际处理请求的对象区分开来,从而实现松耦合设计。这些请求被称为事件,处理这些请求的代码被称为事件处理器。
现假设你正在开发一个支持剪切、复制、粘贴等鼠标操作的应用程序。应用中能以不同的方式触发这些操作,例如一些菜单操作或者键盘的快捷键。
Command对象可以集中对每一个操作的处理。每个操作对应一个命令。所以剪切、复制、粘贴操作分别对应一个命令。
因为命令集中处理,所以经常出现在一些需要撤销的应用中。
表示图:
参与者:
在这种模式中参与的对象有:
Client--代码中的run()函数
引用Receiver对象。
Receiver--代码中的Calculator
了解如何执行命令
保留执行命令的历史记录
Command--代码中的Command
Invoker--代码中用户按下按钮
例子:
在我们的例子中,计算器有四种操作,加减乘除,每种操作被封装成一个单独的Command对象。
计算器有个命令堆栈,每种命令执行后被压入该堆栈中,撤销操作时,只需要弹出堆栈,执行弹出的命令对象的相反操作的方法。
JS的函数对象(以及回调)是天然的命令对象,他们能够像对象一样传递,实际上,他们是本质上也是对象。
log函数助于收集和展示结果。
function add(x, y) { return x + y; }
function sub(x, y) { return x - y; }
function mul(x, y) { return x * y; }
function div(x, y) { return x / y; }
var Command = function (execute, undo, value) {
this.execute = execute;
this.undo = undo;
this.value = value;
}
var AddCommand = function (value) {
return new Command(add, sub, value);
};
var SubCommand = function (value) {
return new Command(sub, add, value);
};
var MulCommand = function (value) {
return new Command(mul, div, value);
};
var DivCommand = function (value) {
return new Command(div, mul, value);
};
var Calculator = function () {
var current = 0;
var commands = [];
function action(command) {
var name = command.execute.toString().substr(9, 3);
return name.charAt(0).toUpperCase() + name.slice(1);
}
return {
execute: function (command) {
current = command.execute(current, command.value);
commands.push(command);
log.add(action(command) + ": " + command.value);
},
undo: function () {
var command = commands.pop();
current = command.undo(current, command.value);
log.add("Undo " + action(command) + ": " + command.value);
},
getCurrentValue: function () {
return current;
}
}
}
// log helper
var log = (function () {
var log = "";
return {
add: function (msg) { log += msg + "\n"; },
show: function () { alert(log); log = ""; }
}
})();
function run() {
var calculator = new Calculator();
// issue commands
calculator.execute(new AddCommand(100));
calculator.execute(new SubCommand(24));
calculator.execute(new MulCommand(6));
calculator.execute(new DivCommand(2));
// reverse last two commands
calculator.undo();
calculator.undo();
log.add("\nValue: " + calculator.getCurrentValue());
log.show();
}
博客原文:
http://www.dofactory.com/javascript/command-design-pattern