组合模式的定义
组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构。
曾探《JavaScript设计模式与开发实践》
组合模式用于处理组合对象的请求。
更强大的宏命令
关于宏命令的实现,我在命令模式的笔记中已经提及了。
在组合模式中,可以对宏命令做更好的处理,将一些小的宏命令合成大的宏命令,下面引用《JavaScript设计模式与开发实践》的代码来说明这点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| <html> <body> <button id="button">按我</button> <script> var MacroCommand = function() { return { commandsList: [], add: function(command) { this.commandsList.push(command) }, execute: function() { for (let i = 0, command; command = this.commandsList[i++];) { command.execute(); } } } }; var openAcCommand = { execute: function() { console.log('打开空调'); } }; var openTvCommand = { execute: function() { console.log('打开电视'); } }; var openSoundCommand = { execute: function() { console.log('打开音响'); } }; var macroCommand1 = MacroCommand(); macroCommand1.add(openTvCommand); macroCommand1.add(openSoundCommand); var closeDoorCommand = { execute: function() { console.log('关门') } }; var openPcCommand = { execute: function() { console.log('开电脑'); } }; var openQQCommand = { execute: function() { console.log('登录QQ'); } }; var macroCommand2 = MacroCommand(); macroCommand2.add(closeDoorCommand); macroCommand2.add(openPcCommand); macroCommand2.add(openQQCommand); var macroCommand = MacroCommand(); macroCommand.add(openAcCommand); macroCommand.add(macroCommand1); macroCommand.add(macroCommand2); var setCommand = (function(command) { document.getElementById('button').onclick = function() { command.execute(); } })(macroCommand); </script> </body> </html>
|
结果
这里的命令发出是以链式的方法发出的,一个大的宏命令告知其包含的命令执行execute方法,若其中还有宏命令,则继续告知,若为普通命令,则直接执行execute方法。
该例子的树形结构为
组合模式的注意点
- 组合模式不是父子关系
组合模式是一种HAS-A的关系,而不是IS-A的关系。
HAS-A:一种事物为另一种事物上的一个部件
IS-A:一种事物为另一种事物中的一种分类
组合对象包含一组叶对象,方法的真正执行是在叶对象上,其他对象方法的执行实际上起到了一个命令传递的作用。
命令方法的一致性
要保证对象能从根一直传递到叶,必须保证方法名是相同的,如上面例子中都是execute。
一个对象不能有两个“父对象”
这里的“父对象”指将命令传给该对象的对象,如果一个对象有两个“父对象”,意味着在命令传递过程中,它的方法会被执行两次,假如它不是叶对象,其下的所有对象的方法都会被执行两次。
组合模式的优点
- 对于树中的对象“平等”对待
不管树中的对象是组合对象或者叶节点对象,都执行相同的方法
- 迭代树关系数据的便利性
只需要执行根节点的方法就可以对整棵树执行该方法,对迭代一棵树来说很方便
组合模式的缺点
- 树结构中对象的相似性过高
为了保证树结构中的节点能被遍历,每个节点的方法大都是相同的,这样在看代码时很难区分对象,只有在执行的时候才能区分对象
- 创建过多的对象
组合模式除了为每一个执行方法的对象构建一个对象,还要构建多个组合对象来构成最后完整的树结构,在这个过程中可能会构建过多的对象,而系统可能担负不起过多的对象。
参考自曾探的《JavaScript设计模式与开发实践》