命令模式最常见的应用场景:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
// 最主要的逻辑就是把命令对象抽象出来,然后就出来了一个command,然后自然而然一个连接目标对象和命令对象的方法就被需要了
var setCommand=function(target,command){
target.onClick=()=>{
command.excute()
}
}
// 一般来说,命令会封装在一个对象里,如:
var MenuBar={
refresh:function(){
console.log('刷新')
}
}
// 针对这种情况,需要把命令对象改造成合适的command的形式供setCommand调用
var refreshMenuBar=function(receiver){
return {
excute:function(){
receiver.refresh()
}
}
}
命令模式最核心的还是:将命令抽象出一个对象,然后随机应变构建出将现有命令与接收命令的对象连接起来的函数。
撤销命令
撤销命令显然需要记录下已经执行过的命令,撤销时从堆栈中依次取出。
命令队列
根据场景的不同,命令的执行表现也不同。有时候命令会在短时间内发出多个,这些命令对象可以依次执行也可以执行最近的一次命令。依次执行的情况下就需要维护一个命令队列。
宏命令
宏命令本身是对基础命令模式的再次组合,无非是在命令对象之后再抽象出一层宏命令对象。
// 自己先实现一个
var macroCommand=function(){
var stack=[]
return {
add:function(command){
stack.push(command)
},
excute:function(){
for(var i=0;i<stack.length;i++){
var curCommand=stack[i]
curCommand.excute()
}
}
}
}
// 书中实现的
var macroCommand=function(){
return {
commandsList:[],
add:function(command){
this.commandsList.push(command)
},
excute:function(){
for(var i=0,command;command=this.commandsList[i++];){
command.excute()
}
}
}
}
傻瓜命令和智能命令
傻瓜命令在命令对象中保存有receiver,这种命令更接近于一种特定化的实例。
智能命令对象中命令是可以直接实现的,和receiver无关。
没有接收者的智能命令,退化到和策略模式非常接近,从代码结构上已经无法分辨它们,能分辨的只有它们的意图的不同。