JS设计模式——命令模式

命令模式用于解耦请求发送者和接收者。

命令是指一个执行某些特定任务的指令。在命令模式中,命令被封装为command对象,接收者与command对象通过命令工厂关联起来。

一、JavaScript的命令模式

传统的面向对象的编程语言中,命令模式将过程式的请求调用封装在command对象的execute方法中。在JavaScript中我们可以利用闭包的特性,将接收者封装在闭包形成的作用域中,执行命令的操作依靠回调函数即可,更加简单。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//接收者
var Menu={
refresh:function(){
console.log("refresh menu");
}
};

//命令对象工厂
var RefreshMenuCommand=function(receiver){
return { //接收者被封闭在闭包中
ececute: function(){
receiver.refresh();
}
};
};

//组装命令发送者与接收者
var setCommand=function(button,command){
button.onclick=function(){
command.execute();
};
};

//实例化一个命令对象
var refreshMenu=RefreshMenuCommand(Menu);
//关联接收者和发送者
setCommand(button,refreshMenu);

二、利用命令模式实现小球轨迹追踪

先看效果::

来看关键的几处地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//实际执行的任务接收者
var animations = {
up: function() {
······

//命令工厂
var makeCommand = function(receiver, state) {
return function() {
receiver[state]();
};
};

//关联命令接收者和发送者
$(document).on("keypress", function(e) {
//实例化一个命令对象
var command = makeCommand(animations, commands[e.keyCode]);
//对象入栈
commandStack.push(command);
//执行命令
command();
});

三、宏命令

宏命令是一组命令的集合,通过执行宏命令的方式可以一次执行一批命令。宏命令适用于需要分批处理命令的情况,执行命令的时候可以针对一组命令做出优化。下面是一个典型的宏命令实现方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var MacroCommand=function(){
return {
commandList:[], //命令队列,用于存储命令
add: function(){ //add方法,用于添加命令
this.commandList.push(command);
},
exccute: function(){ //execute方法,用于执行队列中的命令
for(var i=0,command;command=this.comamndList[i++];){
command.execute();
}
}
};
};

//使用方法
var macroCommand=MacroCommand(); //实例化一个宏命令对象
macroCommand.add(command);
······
macroCommand.execute(); //指令所有命令

四、总结

  • 在command对象中保存一个接收者来执行请求的操作,这种命令对象是傻瓜命令
  • 在command对象中直接就可以实现请求操作的命令对象是智能命令,这种情形和策略模式很接近;
  • 使用setTimeout时要注意:第一个参数表示要执行的函数,不可带参数。如果需要向执行的函数传递参数,可以直接写在延迟时间的后面。如果给第一个参数带上参数,它会立即执行,setTimeout得到的是它执行后返回的对象。