有时需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么,此时希望用一种松耦合的方式来设计软件,使请求发送者和请求接收者能够消除彼此间的耦合关系。
1.基本实现
let setCommand = function (button, command) { //安装命令方法
button.onclick = function () {
command.execute();
}
}
let MenuBar = { //定义命令
refresh: function () {
console.log('刷新');
}
}
let RefreshMenuBarCommand = function (receiver) { //执行命令
return {
execute: function () {
receiver.refresh();
}
}
}
let refreshMenuBarCommand = RefreshMenuBarCommand(MenuBar);
setCommand(button, refreshMenuBarCommand);
以上代码实现了一个基本的命名模式,但通常需要实现一个撤销命名undo来撤回修改操作,以下代码中实现。
2.撤销命令
let Node = {
value: 1,
set: function (val) {
this.value = val;
},
get: function () {
return this.value;
}
}
let SetNodeCommand = function (receiver) {
this.oldVal = null;
return {
execute: function (value) {
this.oldVal = receiver.get();
receiver.set(value);
},
undo: function () {
receiver.set(this.oldVal);
}
}
}
let GetNodeCommand = function (receiver) {
return {
execute: function () {
return receiver.get();
}
}
}
let setNodeCommand = new SetNodeCommand(Node);
let getNodeCommand = new GetNodeCommand(Node);
setNodeCommand.execute(5);
setNodeCommand.undo();
console.log(getNodeCommand.execute()); //1
实现撤销命名非常简单,只需要在执行当前命令之前,将当前状态保存下来就可以了。使用撤销命名可以实现诸如文档操作中的(Ctrl+Z)等操作,但是以上代码还存在缺陷,即只能够撤回一次操作,因此我们通过引入堆栈来缓存每一次操作。同时加入重做功能。
3.重做命令
let Node = {
value: 1,
set: function (val) {
this.value = val;
},
get: function () {
return this.value;
}
}
let SetNodeCommand = function (receiver) {
let oldVal = [];
let repeList = [];
return {
execute: function (value) {
let oldValue = receiver.get();
oldVal.push(oldValue);
receiver.set(value);
},
undo: function () {
repeList.push(receiver.get());
receiver.set(oldVal.pop());
},
repe: function () {
receiver.set(repeList.pop());
}
}
}
let GetNodeCommand = function (receiver) {
return {
execute: function () {
return receiver.get();
}
}
}
let setNodeCommand = new SetNodeCommand(Node);
let getNodeCommand = new GetNodeCommand(Node);
setNodeCommand.execute(5);
setNodeCommand.undo();
setNodeCommand.repe();
console.log(getNodeCommand.execute()); //5
4.宏命令
let Command1 = {
excute: function () {
console.log("执行命令1");
}
}
let Command2 = {
excute: function () {
console.log("执行命令2");
}
}
let Command3 = {
excute: function () {
console.log("执行命令3");
}
}
let MacroCommand = function () {
return {
commandList: [],
add: function (command) {
this.commandList.push(command);
},
excute: function () {
for (let i = 0, command; command = this.commandList[i++];) {
command.excute();
}
}
}
}
let macroCommand = new MacroCommand();
macroCommand.add(Command1);
macroCommand.add(Command2);
macroCommand.add(Command3);
macroCommand.excute();
宏命令就是一组命令的集合,可以一次执行一批命令。