命令模式

比喻定义

某位客人点餐或着打电话定餐后,服务员把他的需求定在订清单上,然后交给后厨,客人不用关心是哪个厨师帮他炒菜。客人可以要求延迟炒菜,或取消订单,只要订单在厨师便不会忘记。点餐人过多,厨师还可以按单餐的顺序炒菜.

记录订餐信息的清单,便是命令模式中的命令对象

命令模式中的指令指的是一个执行某些特定事情的指令

常见应用场景

有时候需求向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。希望用一种松耦合的方式来设计 程序 ,使得请求发者和请求接收者能够消除彼此之间的耦合关系。

Javascript中的命令模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var bindClick = function( button, func ) {
button.addEventListener('click', func, false);
};

var MenuBar = {
refresh: function() {
console.log('refresh menu!');
}
};

var SubMenu = {
add: function() {
console.log('add sub menu!');
},
del: function() {
console.log('del sub menu!');
}
};

bindClick( button1, MenuBar.refresh );
bindClick( button2, SubMenu.add );
bindClick( button3, SubMenu.del );

upgrade

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
28
29
30
31
32
var setCommand = function( button, func ) {
button.addEventListener('click', func, false);
};

var MenuBar = {
refresh: function() {
console.log('refresh menu!');
};
};

var RefreshMenuBarCommand = function( receiver ) {
return function() {
receiver.refresh();
}
};

var refreshMenuBarCommand = RefreshMenuBarCommnad( MenuBar );
setCommand( button1, refreshMenuBarCommand );
// upgrade more
var RefreshMenuBarCommand = function( receiver ) {
return {
execute: function() {
receiver.refresh();
}
};
};

var setCommand = function( button, command ) {
button.addEventListener( 'click', function() {
command.execute();
}, false );
};

撤销命令

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
28
29
30
var ball = document.getElementById('ball');
var pos = document.getElementById('pos');
var moveBtn = document.getElementById('moveBtn');
var cancleBtn = docuemnt.getElementById('cancleBtn');

var MoveCommand = function( receiver, pos ) {
this.reciver = receiver;
this.pos = pos;
this.oldPos = null;
};

MoveCommnad.prototype.execute = function() {
this.receiver.start(‘left’, this.pos, 1000, 'strongEaseOut');
this.oldPos = this.receiver.dom.getBoundingClientRect()[this.receiver.propertyName];
};

MoveCommand.prototype.undo = function() {
this.receiver.start('left', this.oldPos, 1000, 'strongEaseOut');
}

var moveCommand;
moveBtn.addEventListener('click', function() {
var animae = new Animate('ball');
moveCommand = new MoveCommand( animate, pos.value);
moveCommand.execute();
}, false);

cancleBtn.addEventListener('click', function(){
moveCommand.undo();
}, false);

撤销和重做

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var Ryu = {
attack: function() {
console.log('攻击');
},
defense: function() {
console.log('防御');
},
jump: function() {
console.log('跳跃');
},
crouch: function() {
console.log('蹲下');
}
};

var makeCommand = function( receiver, state ) {
return function() {
receiver[state]();
}
};

var commands = {
'119': 'jump',
'115': 'crouch',
'97': 'defense',
'100': 'attack'
};

var commandStack = [];
document.addEventListener('keypress', function(ev) {
var keyCode = ev.keyCode,
command = makeCommand( Ryu, commands[ keyCode ] );
if(command) {
command();
commandStack.push( command );
}
document.getElementById('replay').addEventListener('click', function() {
var command;
while(command = commandStack.shift()) {
command();
}
}, false);
}, false);

宏命令

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
28
29
30
31
32
33
34
35
36
37
var closeDoorCommand = {
execute: function() {
console.log('colse door!');
};
};

var openPcCommand = {
execute: function() {
console.log('open pc!');
};
};

var openQQCommand = {
execute: function() {
console.log('login QQ!');
}
};

var MacroCommand = function() {
return {
commandList: [],
add: function(command) {
this.commandList.push(command);
},
execute: function() {
this.commandList.forEach(function(command){
command.execute();
});
}
};
};

var macroCommand = MacroCommand();
macroCommand.add( colseDoorCommand );
macroCommand.add( openPcCommand );
macroCommand.add( openQqCommand );
macroCommand.execute();

智能命令与傻瓜命令

closeDoorCommand中没有包含任何recevier,包含recevier的叫傻瓜命令,能更好的解藕;
不包含的叫智能命令。

拓展:对比一下,函数的传参与不传参。

拓展:什么东西叫纯函数?