标签:opera 抽象类 最大 依次 性能 一起 lis 启动命令 模式
我们知道地球和一些其他行星围绕着太阳旋转,也知道在一个原子中,有许多电子围绕着原子核旋转。可以大胆推测,一个电子中也包含了另一个宇宙,我们所熟知的银河系
也只是另一个浩大空间的组成部分.....
在程序设计中,组合模式就是用小的对象来构建更大的对象。
先来看一个简单的例子:
1 var closeDoorCommand = { 2 excute: function() { 3 console.log(‘关门‘); 4 } 5 }; 6 7 var openPcCommand = { 8 excute: function() { 9 console.log(‘开电脑‘); 10 } 11 }; 12 13 var openQQCommand = { 14 excute: function() { 15 console.log(‘登录QQ‘); 16 } 17 }; 18 19 var MacroCommand = function() { 20 return { 21 commandList: [], 22 add: function(command) { 23 this.commandList.push(command); 24 }, 25 excute: function() { 26 for(var i = 0, command; command = this.commandList[ i++ ]; ){ 27 command.excute(); 28 } 29 } 30 } 31 }; 32 33 var macroCommand = new MacroCommand(); 34 macroCommand.add( closeDoorCommand ); 35 macroCommand.add( openPcCommand ); 36 macroCommand.add( openQQCommand ); 37 macroCommand.excute();
1.首先我们定义了一系列小的命令对象,他们有关门、打开电脑、登录QQ等一系列具有顺序的操作,每个命令都具有一个可供执行的execute方法
2.定义了一个可以包含其他命令的宏命令,这个宏命令包含了一个等待执行的命令队列及启动命令的execute方法。
在宏命令中,保存了对每个子对象的引用,并且实现了和子对象相同的方法:execute方法,只要调用宏命令的execute方法,程序就会依次执行commandList中的所有命令。
组合模式的用途:
组合模式将对象组合成树的结构形式,以表示“部分-整体”的层次结构。除了用来表示树形结构之外,组合模式的另一个好处是通过对象的多态性表现,使得用户对单个对象和组合对象
的使用具有一致性。
这些在实际开发中会给用户带来相当大的便利性。我们只需要确定它是一个命令,并且这个命令拥有可执行的execute方法,那么这个命令就可以被添加的宏命令中。
其实,利用组合模式可以实现更强大的宏命令。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>组合模式</title> 6 </head> 7 <body> 8 <div> 9 <button id="button">万能遥控</button> 10 </div> 11 <script> 12 13 var MacroCommand = function() { 14 return { 15 commandList: [], 16 add: function(command) { 17 this.commandList.push(command); 18 }, 19 execute: function() { 20 for(var i = 0, command; command = this.commandList[ i++ ]; ){ 21 command.execute(); 22 } 23 } 24 } 25 }; 26 27 var openAcCommand = { 28 execute: function() { 29 console.log(‘打开空调‘); 30 } 31 }; 32 33 /*家里的电视和音响是连在一起的,所以可以用一个宏命令来组合打开电视和打开音响的命令*/ 34 35 var openTVCommand = { 36 execute: function() { 37 console.log(‘打开电视‘); 38 } 39 }; 40 41 var openSoundCommand = { 42 execute: function() { 43 console.log(‘打开音响‘); 44 } 45 }; 46 47 var macroCommand1 = MacroCommand(); 48 macroCommand1.add( openTVCommand ); 49 macroCommand1.add( openSoundCommand ); 50 51 52 /*关门、打开电脑和打开登录QQ的命令*/ 53 var closeDoorCommand = { 54 execute: function() { 55 console.log(‘关门‘); 56 } 57 }; 58 59 var openPcCommand = { 60 execute: function() { 61 console.log(‘开电脑‘); 62 } 63 }; 64 65 var openQQCommand = { 66 execute: function() { 67 console.log(‘登录QQ‘); 68 } 69 }; 70 71 72 var macroCommand2 = MacroCommand(); 73 macroCommand2.add( closeDoorCommand ); 74 macroCommand2.add( openPcCommand ); 75 macroCommand2.add( openQQCommand ); 76 77 /*把所有的命令组合成一个“超级命令”*/ 78 79 var macroCommand = MacroCommand(); 80 macroCommand.add( openAcCommand ); 81 macroCommand.add( macroCommand1 ); 82 macroCommand.add( macroCommand2 ); 83 84 /*事件绑定*/ 85 var setCommand = (function(command) { 86 document.getElementById(‘button‘).onclick = function() { 87 command.execute(); 88 } 89 })(macroCommand) 90 </script> 91 </body> 92 </html>
抽象类在组合模式中的作用:
前面说过,组合模式最大的优点在于可以一致性的对待组合对象和基本对象。客户不需要知道当前处理的是宏命令还是普通命令,只要它是一条命令,并且拥有execute方法,这个命令就可以
被添加到书中
这种透明性带来的便利,在静态语言中体现的尤为明显。比如在Java中,实现组合模式的关键是Composite类和Leaf类都必须继承自一个Component抽象类。
代码如下:
1 // Java代码 2 public abstract class Component{ 3 public void add( Component child) {} 4 public void remove( Component child){} 5 } 6 7 public class Composite extends Component{ 8 public void add( Component child) {} 9 public void remove( Component child) {} 10 } 11 12 public class Leaf extends Component{ 13 public void add( Component child){ 14 throw new UnsupportedOperationException() 15 } 16 public void remove( Component child){} 17 18 } 19 20 public class client{ 21 public static void main( String args[]) { 22 Component root = new Composite(); 23 Component c1 = new Composite(); 24 Component c2 = new Composite(); 25 26 Component leaf1 = new Leaf(); 27 Component leaf2 = new Leaf(); 28 29 root.add(c1); 30 root.add(c2); 31 32 c1.add(leaf1); 33 c1.add(leaf2); 34 35 root.remove(); 36 } 37 }
在JavaScript这种动态语言中,对象的多态性是与生俱来的,也没有编译器去检查变量的类型,在JavaScript中实现组合模式的难点在于要保证组合对象和叶对象拥有同样的方法,这通常需要鸭子类型的思想对他们进行接口检查。
在JavaScript中实现组合模式,看起来缺乏一些严谨性,代码算不上安全,但能更快和自由的开发,这既是JavaScript的缺点,也是优点。
一些值得注意的地方:
最后,说一下组合模式中引用父对象的例子。
1 var Folder = function(name) { 2 this.name = name; 3 this.parent = null; 4 this.files = []; 5 } 6 Folder.prototype.add = function(file) { 7 file.parent = this; 8 this.files.push(file); 9 } 10 Folder.prototype.scan = function() { 11 console.log(‘开始扫描文件夹:‘ + this.name); 12 for (var i = 0, file, files = this.files; file = files[ i++ ]; ) { 13 file.scan(); 14 } 15 } 16 Folder.prototype.remove = function() { 17 if (!this.parent) { // 根节点或者树外的游离节点 18 return; 19 } 20 for (var files = this.parent.files, l = files.length - 1; l >= 0; l--) { 21 var file = files[l]; 22 if (file === this) { 23 fils.splice(l, 1); 24 } 25 } 26 } 27 28 var File = function(name) { 29 this.name = name; 30 this.parent = null; 31 } 32 33 File.prototype.add = function() { 34 throw new Error(‘不能添加在文件下面‘); 35 } 36 37 File.prototype.scan = function() { 38 console.log(‘开始扫描文件:‘ + this.name); 39 } 40 41 File.prototype.remove = function() { 42 if (!this.parent) { 43 return; 44 } 45 for (var files = this.parent.files, l = files.length - 1; l >= 0; l--) { 46 if (file === this ) { 47 files.splice(l ,1); 48 } 49 } 50 }
总结:何时使用组合模式
组合模式如果运用得当,可以大大简化客户的代码。一般来说,组合模式适用于以下这两种情况:
标签:opera 抽象类 最大 依次 性能 一起 lis 启动命令 模式
原文地址:https://www.cnblogs.com/cangqinglang/p/9824432.html