命令模式是一种组织型模式,主要用在把调用对象(用户界面、API和代理等)与实现操作的对象隔离开。也就是说 ,凡是两个对象间的互动方式需要更高的模块化程度时都可以用到这种模式。
命令模式的好处:1、提高程序的模块化程度和灵活性。(运用得当);2、实现取消和状态恢复等复杂的有用特性非常容易。
例子:菜单组合对象
1 /** 2 * 菜单组合对象 3 */ 4 5 /*command,Composite and MenuObject interfaces*/ 6 var Command = new Interface("Compand",["execute"]); 7 var Composite = new Interface("Composite",["add","remove","getChild","getElement"]); 8 var MenuObject = new Interface("MenuObject",["show","hide"]); 9 10 /*MenuBar class, a composite*/ 11 var MenuBar = function(){ 12 this.menus = {}; 13 this.element = document.createElement("ul"); 14 this.element.className = "menu-bar"; 15 this.element.style.display = "none"; 16 } 17 MenuBar.prototype = { 18 add:function(menuObject){ 19 Interface.ensureImplements(menuObject,Composite,MenuObject); 20 this.menus[menuObject.name] = menuObject; 21 this.element.appendChild(this.menus[menuObject.name].getElement()); 22 }, 23 remove:function(name){ 24 delete this.menus[name]; 25 }, 26 getChild:function(name){ 27 return this.menus[name]; 28 }, 29 getElement:function(){ 30 return this.element; 31 }, 32 show:function(){ 33 this.element.style.display = "block"; 34 for(name in this.menus){ 35 this.menus[name].show(); 36 } 37 }, 38 hide:function(){ 39 this.element.style.display = "none"; 40 } 41 } 42 43 /*Menu class a composite*/ 44 //备注:这里为了获取Menu对象的父对象,所以多传了一个parent,同时在实现的接口下,又多加了两个方法:showContainer和hideContainer 45 var Menu = function(name,parent){ 46 this.name = name; 47 this.items = {}; 48 this.parent = parent; 49 this.element = document.createElement("li"); 50 this.element.className = "menu"; 51 this.element.innerHTML = this.name; 52 this.element.style.display = "none"; 53 this.container = document.createElement("ul"); 54 this.element.appendChild(this.container); 55 56 var that = this; 57 this.element.addEventListener("click",function(e){ 58 e.preventDefault(); 59 e.stopPropagation(); 60 //这里在显示当前菜单选项的时候,把其他的选项全部隐藏掉 61 var menus = that.parent.menus; 62 if(menus){ 63 for(var name in menus){ 64 menus[name].hideContainer(); 65 } 66 } 67 that.showContainer(); 68 },false); 69 document.body.addEventListener("click",function(e){ 70 e.preventDefault(); 71 e.stopPropagation(); 72 that.hideContainer(); 73 },false); 74 }; 75 76 Menu.prototype = { 77 add:function(menuItemObject){ 78 Interface.ensureImplements(menuItemObject,Composite,MenuObject); 79 this.items[menuItemObject.name] = menuItemObject; 80 this.container.appendChild(this.items[menuItemObject.name].getElement()); 81 }, 82 remove:function(name){ 83 delete this.items[name]; 84 }, 85 getChild:function(name){ 86 return this.items[name]; 87 }, 88 getElement:function(){ 89 return this.element; 90 }, 91 show:function(){ 92 this.element.style.display = "block"; 93 for(name in this.items){ 94 this.items[name].show(); 95 } 96 }, 97 hideContainer:function(){ 98 this.container.style.display = "none"; 99 }, 100 showContainer:function(){ 101 this.container.style.display = "block"; 102 }, 103 hide:function(){ 104 this.element.style.display = "none"; 105 } 106 } 107 108 /*MenuItem class, a leaf*/ 109 var MenuItem = function(name,command){ 110 Interface.ensureImplements(command,Command); 111 this.name = name; 112 this.element = document.createElement("li"); 113 this.element.className = "menu-item"; 114 this.element.style.display = "none"; 115 this.anchor = document.createElement("a"); 116 this.anchor.href = "#"; 117 this.anchor.innerHTML = this.name; 118 this.element.appendChild(this.anchor); 119 120 this.anchor.addEventListener("click",function(e){ 121 e.preventDefault(); 122 command.execute(); 123 }); 124 }; 125 126 MenuItem.prototype = { 127 add:function(){}, 128 remove:function(){}, 129 getChild:function(){}, 130 getElement:function(){return this.element;}, 131 show:function(){ 132 this.element.style.display = "block"; 133 }, 134 hide:function(){ 135 this.element.style.display = "none"; 136 } 137 }
界面:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>菜单对象</title> 6 <style type="text/css"> 7 #container{margin:0 auto;padding:0; border:1px solid #ccc; width:500px; height:50px; font-family: "微软雅黑"; font-size: 14px; text-align: center;} 8 .menu-bar{list-style: none;padding:0;width:100%;height:50px; margin-left:50px;} 9 .menu-bar .menu{float:left; width:80px; text-align: center; cursor: pointer;height:30px; line-height:30px;} 10 .menu-bar .menu:hover{background:#0000DD; color:#fff;} 11 .menu-bar .menu ul{list-style:none;width:80px; margin:0;padding:0; background:#ddd; display: none; margin-top:5px; border: 1px solid black;} 12 /*.menu-bar .menu:nth-of-type(1) ul{display: block;}*/ 13 .menu-bar .menu .menu-item{width:70px;height:30px; line-height: 30px; border-bottom: 1px dashed #ccc;} 14 .menu-bar .menu .menu-item a{text-decoration: none;} 15 16 #result{ 17 margin:150px auto; height:50px; line-height: 50px; border: 2px solid red; width:300px; text-align: center; font-family: "微软雅黑"; font-size: 16px; 18 } 19 </style> 20 </head> 21 <body> 22 <div id="container"> 23 24 </div> 25 26 <div id="result"></div> 27 </body> 28 </html> 29 <script type="text/javascript" src="Interface.js"></script> 30 <script type="text/javascript" src="Menu.js"></script> 31 <script type="text/javascript"> 32 var oResult = document.getElementById("result"); 33 //定义每个菜单的action 34 function FileActions(){} 35 FileActions.prototype = { 36 open:function(){ 37 oResult.innerHTML = "open command is executed"; 38 }, 39 close:function(){ 40 oResult.innerHTML = "close command is executed"; 41 }, 42 save:function(){ 43 oResult.innerHTML = "save command is executed"; 44 }, 45 saveAs:function(){ 46 oResult.innerHTML = "saveAs command is executed"; 47 } 48 } 49 50 function EditActions(){} 51 EditActions.prototype = { 52 cut:function(){ 53 oResult.innerHTML = "cut command is executed"; 54 }, 55 copy:function(){ 56 oResult.innerHTML = "copy command is executed"; 57 }, 58 paste:function(){ 59 oResult.innerHTML = "paste command is executed"; 60 }, 61 delete:function(){ 62 oResult.innerHTML = "delete command is executed"; 63 } 64 } 65 66 function InsertActions(){} 67 InsertActions.prototype.insert = function(){ 68 oResult.innerHTML = "insert command is executed"; 69 } 70 71 function HelpActions(){} 72 HelpActions.prototype.help = function(){ 73 oResult.innerHTML = "help command is executed"; 74 } 75 76 77 /*MenuCommand class. a command object*/ 78 var MenuCommand = function(action){ 79 this.action = action; 80 } 81 MenuCommand.prototype.execute = function(){ 82 this.action(); 83 } 84 85 var fileActions = new FileActions(); 86 var editActions = new EditActions(); 87 var insertActions = new InsertActions(); 88 var helpActions = new HelpActions(); 89 90 var appMenuBar = new MenuBar(); 91 92 /*fileMenu*/ 93 var fileMenu = new Menu("File",appMenuBar); 94 95 fileMenu.add(new MenuItem("Open",new MenuCommand(fileActions.open))); 96 fileMenu.add(new MenuItem("Close",new MenuCommand(fileActions.close))); 97 fileMenu.add(new MenuItem("Save",new MenuCommand(fileActions.save))); 98 fileMenu.add(new MenuItem("Save As",new MenuCommand(fileActions.saveAs))); 99 100 appMenuBar.add(fileMenu); 101 102 /*editMenu*/ 103 var editMenu = new Menu("Edit",appMenuBar); 104 105 editMenu.add(new MenuItem("Cut",new MenuCommand(editActions.cut))); 106 editMenu.add(new MenuItem("Copy",new MenuCommand(editActions.copy))); 107 editMenu.add(new MenuItem("Paste",new MenuCommand(editActions.paste))); 108 editMenu.add(new MenuItem("Delete",new MenuCommand(editActions.delete))); 109 110 appMenuBar.add(editMenu); 111 112 /*the insert menu*/ 113 114 var insertMenu = new Menu("Insert",appMenuBar); 115 insertMenu.add(new MenuItem("The Block",new MenuCommand(insertActions.insert))); 116 appMenuBar.add(insertMenu); 117 118 /*The help menu*/ 119 var helpMenu = new Menu("Help",appMenuBar); 120 helpMenu.add(new MenuItem("TheHelp",new MenuCommand(helpActions.help))); 121 122 appMenuBar.add(helpMenu); 123 124 /*Build the menu bar*/ 125 document.getElementById("container").appendChild(appMenuBar.getElement()); 126 appMenuBar.show(); 127 128 </script>