一、定义
命令模式是最简单和优雅的模式之一,命令模式中的命令(command)指的是一个执行某些特定事情的指令。
6.1 基本概念
命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收 者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
例如: 对于拿订餐来说,客人需要向厨师发送请求,但是完全不知道这些厨师的名字和联系方式,也不 知道厨师炒菜的方式和步骤。客人只关心菜品能准时上就行。
// 模拟拳皇的场景
const Ryu = {
attack: () => { console.log('攻击 => ',); },
defense: () => { console.log('防御 => ',); },
jump: () => { console.log('跳跃 => ',); },
crouch: () => { console.log('蹲下 => ',); },
};
const commands = {
119: 'jump', // W
115: 'crouch', // S
97: 'defense', // A
100: 'attack', // D
};
// 创建命令
const makeCommand = (receiver, state) => receiver[state];
const commandStack = [];
document.onkeypress = function(e) {
const command = makeCommand(Ryu, commands[e.keyCode]);
if (command) {
command(); // 执行命令
commandStack.push(command);
}
}
// 回放
const replay = document.getElementById('replay');
replay.onclick = function(e) {
let command;
while (command = commandStack.shift()){
command();
};
}
6.2 宏命令
宏命令是一组命令的集合,通过执行宏命令的方式,可以一次执行一批命令。批量执行, 相当于一键操作。想象一下,家 里有一个万能遥控器,每天回家的时候,只要按一个特别的按钮,它就会帮我们关上房间门,顺便打开电脑并登录 QQ。
const commandSet = {
closeDoor: () => { console.log('关上房门 => ',); },
openPc: () => { console.log('打开电脑 => ',); },
openQQ: () => { console.log('打开qq1 => ',); },
};
class MacroCommand {
commandList = [];
add = (command) => this.commandList.push(command);
execute = () => this.commandList.forEach((item) => item());
replay = () => {
let command;
while(command = this.commandList.shift()) {
command();
}
};
print = () => console.log('this.commandList => ',this.commandList);
}
const mc = new MacroCommand();
const { closeDoor, openPc, openQQ } = commandSet;
mc.add(closeDoor);
mc.add(openPc);
mc.add(openQQ);
mc.print();
setTimeout(mc.execute, 2000);
setTimeout(mc.replay, 5000);
二、总结
一般来说,命令模式都会在 command 对象中保存一个接收者来负责真正执行客户的请求,这种情况下命令对象是“傻瓜式”的,它只负责把客户的请求转交给接收者来执行,这种模式的好处是请求发起者和请求接收者之间尽可能地得到了解耦。命令模式还可以完成撤销、排队等功能。