命令模式的用途:
命令模式是最简单和优雅的模式之一,命令模式中的命令(command)指的是一个执行某些特定事情的指令。
命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
命令模式的例子-菜单程序:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>命令模式-菜单程序</title> </head> <body> <button id="button1">1</button> <button id="button2">2</button> <button id="button3">3</button> </body> </html> <script> var button1 = document.getElementById(‘button1‘); var button2 = document.getElementById(‘button2‘); var button3 = document.getElementById(‘button3‘); var setCommand = function(button,command){ button.onclick = function(){ command.execute(); } }; var MenuBar = { refresh: function(){ console.log(‘刷新菜单目录‘); }, add: function(){ console.log(‘增加菜单目录‘); }, del: function(){ console.log(‘删除子菜单‘); } }; var RefreshMenuBarCommand = function(receiver){ this.receiver = receiver; }; RefreshMenuBarCommand.prototype.execute = function(){ this.receiver.refresh(); }; var AddSubMenuCommand = function(receiver){ this.receiver = receiver; }; AddSubMenuCommand.prototype.execute = function(){ this.receiver.add(); }; var DelSubMenuCommand = function(receiver){ this.receiver = receiver; }; DelSubMenuCommand.prototype.execute = function(){ console.log(‘删除子菜单‘); }; var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar); var addSubMenuCommand = new AddSubMenuCommand(SubMenu); var delSubMenuCommand = new DelSubMenuCommand(SubMenu); setCommand(button1,refreshMenuBarCommand); setCommand(button2,addSubMenuCommand); setCommand(button3,delSubMenuCommand); </script>
以上代码模拟传统面向对象语言的命令模式实现。
命令模式的由来,其实是回调函数的一个面向对象的替代品。
var setCommand = function(button,func){ button.onclick = function(){ func(); } }; var MenuBar = { refresh: function(){ console.log(‘刷新菜单目录‘); } }; //用闭包实现的命令模式如下代码所示: var RefreshMenuBarCommand = function(receiver){ return function(){ receiver.refresh(); } }; var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar); setCommand(button1,refreshMenuBarCommand);
//把执行函数改为调用execute方法 var refreshMenuBarCommand = function(receiver){ return{ execute: function(){ receiver.refresh(); } } }; var setCommand = function(button,command){ button.onclick = function(){ command.execute(); } }; var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar); setCommand(button1,refreshMenuBarCommand);
撤销命令:
撤销操作的实现一般是给命令对象增加一个名为unexecute或者undo的方法,在该方法里执行exectue的反向操作。
撤消和重做:
很多时候,我们需要撤销一系列的命令。然而,在某些情况下无法顺利地利用undo操作让对象回到execute之前的状态。
canvas画图中,擦除一条线相对不容易实现。这时候最好的办法是先清除画布,然后把刚才执行过的命令全部重新执行一遍,这一点同样可以利用一个历史列表堆栈办到。记录命令日志,然后重复执行它们,这是逆转不可逆命令的一个好办法。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>撤销和重做命令</title> </head> <body> <button id="replay">播放录像</button> </body> </html> <script> var Ryu = { attack: function(){ console.log(‘攻击‘); }, defense: function(){ console.log(‘防御‘); }, jump: function(){ console.log(‘跳跃‘); }, crouch: function(){ console.log(‘蹲下‘); } }; var makeCommand = function(receiver,state){ return function(){ receiver[state](); } }; var commands = { "119":"jump",//W "115":"crouch",//S "97":"defense",//A "100":"attack"//D }; var commandStack = []; //保存命令的堆栈 document.onkeypress = function(ev){ var keyCode = ev.keyCode, command = makeCommand(Ryu,commands[keyCode]); if(command){ command(); //执行命令 commandStack.push(command);//将刚刚执行过的命令保存进堆栈 } }; document.getElementById(‘replay‘).onclick = function(){ //点击播放录像 var command; while(command = commandStack.shift()){ //从堆栈里依次取出命令并执行 command(); } }; </script>
命令队列
宏命令:
宏命令是一组命令的集合,通过执行宏命令的方式,可以一次执行一批命令。
var closeDoorCommand = { execute: function(){ console.log(‘关门‘); } }; var openPcCommand = { execute: function(){ console.log(‘开电脑‘); } }; var openQQCommand = { execute: function(){ console.log(‘登录QQ‘); } }; var MacroCommand = function(){ return { commandsList:[], add: function(){ for(var i=0,command;command = this.commandsList[i++]; ){ command.execute(); } } } }; var macroCommand = MacroCommand(); macroCommand.add(closeDoorCommand); macroCommand.add(openPcCommand); macroCommand.add(openQQCommand); macroCommand.execute();
宏命令是命令模式与组合模式的联用产物。
智能命令与傻瓜命令
命令模式在JavaScript语言中的一种隐形的模式。
时间: 2024-10-27 12:50:14