命令模式中的命令指的是一个执行某些待定事情的指令。命令模式的运用场景是:有时候需要向某些对象发送请求,但并不知道请求的接收者是谁,也不知道请求的具体操作是什么;此时希望将请求和请求的具体操作分开来设计程序。
设计模式提倡把变化的事物和不变的事物分开,所以命令模式也不例外,所以在分析业务的时候,我们要去思考什么是可变的,什么是不可变的。
<button id="btn1">按钮点击1</button>
<button id="btn2">按钮点击2</button>
<button id="btn3">按钮点击3</button>
<button id="btn4">按钮点击4</button>
var btn1=document.getElementById('btn1');
var btn2=document.getElementById('btn2');
var btn3=document.getElementById('btn3');
var btn4=document.getElementById('btn4');
// 点击之后发生的事情
var setCommand=function(btn,func){
btn.onclick=function(){
func()
// func.excute()
}
}
// 处理发生的事
var requireCommand_one=function(func){
return function(){
return func.call(this)
}
}
//var requireCommand_two=function(receiver){
// return {
// excute:function(){
//receiver()
// }
// }
// }
// 具体什么事情
var bar=function(){
console.log('bar')
}
setCommand(btn1,requireCommand_one(bar))
其实就是单一职责的原理运用。命令模式会给我们的项目带来可维护的代码。以后碰到需求更改还是非常好改的。
命令模式不仅仅是封装运算块,可也给对象增加撤销命令;撤销命令的关键是记录最开始的状态,在执行撤销命令的时候让对象会带最开始的状态即可。
有些对象我们很难去记录最开始的状态,比如用Canvas画布当中,当我们画完一个图,记录这个图每个点的位置其实是非常费力的,那么我们最好的办法是先清除画布,然后再让它重新执行一遍。这就是所谓的重做命令。
实现重做的关键是可以利用一个历史列表堆栈办到,记录命令日志,然后重新执行。
var Ryu={
attack:function(){
console.log('攻击')
},
defence:function(){
console.log('防御')
},
jump:function(){
console.log('跳跃')
}
};
var makeCommond=function(func,state){
return function(){
return func[state]();
}
};
var commands={
'119':'jump',
'115':'crouch',
'97':'defence'
}
var commandStack=[]; //将函数存放在数组,保存起来
// 事件委托
document.onkeypress=function(ev){
var keyCode=ev.keyCode;
command=makeCommond(Ryu,commands[keyCode]);
if(command){
command();
commandStack.push(command)
}
}
// 点击重新播放的按钮,重新播放
document.getElementById('replay').onclick=function(){
var command;
while(command=commandStack.shift()){
command()
}
}
宏命令的概念:宏命令是一组命令的集合,通过执行宏命令的方式,可以一次性执行一批命令。