命令模式
命令模式中的命令(command)指的是一个执行某些特定事情的指令
命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收 者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
记住设计模式的主题,就是把变的事物和不变的事物分离开来。
实例: 假如有这样的一个需求,一个程序员需要负责写ui button,一个程序员负责js编写,那么这种状况下,负责ui的程序员并不知道button的接收者是谁,也不知道接收者接着用来做什么,这种情况下用命令模式更好的处理问题,其实负责ui的程序员只用完成写好接入的接口即可如下setCommand,至于以后做什么,在具体的命令对象里面完成
<div id="app">
<button id='btn1'>按钮1</button>
<button id='btn2'>按钮2</button>
<button id='btn3'>按钮3</button>
</div>
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
function setCommand(btn, command) {
btn.onclick = function() {
command.exculte();
};
}
var refreshObj = {
refresh: function() {
console.log("refresh page");
}
};
var subMenuObj = {
add: function() {
console.log("add menu");
},
delete: function() {
console.log("delete menu");
}
};
var refreshCommand = function(receiver) {
this.receiver = receiver;
};
refreshCommand.prototype.exculte = function() {
this.receiver.refresh();
};
var addMenuCommand = function(receiver) {
this.receiver = receiver;
};
addMenuCommand.prototype.exculte = function() {
this.receiver.add();
};
var deleteCommand = function(receiver) {
this.receiver = receiver;
};
deleteCommand.prototype.exculte = function() {
this.receiver.delete();
};
var refresher = new refreshCommand(refreshObj);
var adder = new addMenuCommand(subMenuObj);
var deleter = new deleteCommand(subMenuObj);
setCommand(btn1, refresher);
setCommand(btn2, adder);
setCommand(btn3, deleter);
从中可以看到我们是如何把请求发送者和请求接收者解耦开的
// 用闭包实现命令模式,执行更加简单,仅仅是执行回调函数即可
function setCommand(btn, command) {
btn.onclick = function() {
command.execute();
};
}
var refreshObj = {
refresh: function() {
console.log("refresh page");
}
};
var subMenuObj = {
add: function() {
console.log("add menu");
},
delete: function() {
console.log("delte menu");
}
};
function refreshCommand(obj) {
return {
execute: function() {
obj.refresh();
}
};
}
function addCommand(obj) {
return {
execute: function() {
obj.add();
}
};
}
function deleteCommand(obj) {
return {
execute: function() {
obj.delete();
}
};
}
var refresher = refreshCommand(refreshObj);
var adder = addCommand(subMenuObj);
var deleter = deleteCommand(subMenuObj);
setCommand(btn1, refresher);
setCommand(btn2, adder);
setCommand(btn3, deleter);
无论是闭包实现命令模式还是用传统的面向对象实现的命令模式,其实都是把命令对象封装到一个地方,然后在保证在setCommand的函数当中可以被执行到即可。
命令模式之撤销
var btn = document.getElementById("btn");
var funObj = {
attack: function() {
console.log("attack");
},
defence: function() {
console.log("defence");
},
jump: function() {
console.log("jump");
},
crouch: function() {
console.log("crouch");
}
};
var commands = {
"97": "defence", // a
"100": "attack", // d
"115": "crouch", // w
"119": "jump" // s
};
function makeCommand(receiver, state) {
if (!state) return;
return function() {
receiver[state]();
};
}
var commandStack = [];
document.onkeypress = function(ev) {
console.log(ev.keyCode);
var key = ev.keyCode;
var command = makeCommand(funObj, commands[key]);
if (command) {
command();
commandStack.push(command);
}
};
btn.onclick = function() {
var comm;
while ((comm = commandStack.shift())) {
comm();
}
};
命令模式在 JavaScript 语言中是一种隐形的模式