命令模式(Command pattern)是一种行为设计模式,它封装的对象包含稍后执行所需要的方法名和该方法需要的参数.

命令对象发送者和接受者并不知道彼此,他们也不关心.这样就将可以消除的发送者和接受者之间的耦合关系.

命令模式带来的好处有:

  1. 重复多次操作(例如:重复下单)
  2. 取消操作(例如:下的订单取消掉)
  3. 取消后重做操作(例如:订单的支付取消,然后再进行支付)
  4. 操作行为回溯(例如:象棋中的悔棋操作)

命令模式结构

  1. 命令的具体行为
  2. 生成命令的工厂方法
  3. 将命令和发送者绑定的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 将命令和发送者绑定
var setCommand = function (button:HTMLDOM, func) {
button.onclick = function () {func()};
};

// 命令的具体行为对象
var MenuBar = {
refresh () {
console.log('刷新菜单');
}
};

// 生成命令的工厂方法
var RefreshMenuBarCommand = function (func) {
return function () {
func.refresh()
}
};

// 生成命令
var refreshMenuBarCommand = RefreshMenuBarCommand(MenuBar)
setCommand(document.getElementById('button1'), refreshMenuBarCommand)

命令队列 和 宏命令

**命令队列 : **当用户的行为很多的时候,我们可以通过命令模式,将用户的行为封装成一个命令,将它放入到一个队列中.当用户一个命令执行完后,我们再去队列中取新的一个命令执行.

**宏命令:**一组命令的集合,通过执行宏命令的方式,可以一次执行一批命令.

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
var closeDoorCommand = {
execute () {
console.log('关门')
}
};

var openPcCommand = {
execute () {
console.log('开电脑')
}
}
var openChromeCommand = {
excute() {
console.log('打开 chrome')
}
}

var MarcoCommand = () {
return {
commandList: [],
add (command) {
this.commandList.push(command)
},
excute () {
for(var i = 0, command; command = this.commandList[i++];) {
command.excute();
}
}
}
}

var marcoCommand = MarcoCommand();
marcoCommand.add(closeDoorCommand);
marcoCommand.add(openPcCommand);
marcoCommand.add(openChromeCommand);
marcoCommand.excute();

面向对象实现方式

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Receiver
class Bulb
{
public function turnOn()
{
echo "Bulb has been lit";
}

public function turnOff()
{
echo "Darkness!";
}
}



// 定义一个命令接口,每个命令将实现它
// Command
interface Command
{
public function execute();
public function undo();
public function redo();
}
class TurnOn implements Command
{
protected $bulb;

public function __construct(Bulb $bulb)
{
$this->bulb = $bulb;
}

public function execute()
{
$this->bulb->turnOn();
}

public function undo()
{
$this->bulb->turnOff();
}

public function redo()
{
$this->execute();
}
}

class TurnOff implements Command
{
protected $bulb;

public function __construct(Bulb $bulb)
{
$this->bulb = $bulb;
}

public function execute()
{
$this->bulb->turnOff();
}

public function undo()
{
$this->bulb->turnOn();
}

public function redo()
{
$this->execute();
}
}

// Invoker
class RemoteControl
{
public function submit(Command $command)
{
$command->execute();
}
}

$bulb = new Bulb();

$turnOn = new TurnOn($bulb);
$turnOff = new TurnOff($bulb);

$remote = new RemoteControl();
$remote->submit($turnOn); // Bulb has been lit!
$remote->submit($turnOff); // Darkness!