设计模式:组合模式
本文简单介绍软件设计模式之:组合模式的概念,用途,及使用。语言使用JavaScript (Nodejs 8.x)。
一、啥叫组合模式?
组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许由更小的“孙对象”构成
撸一段代码,大家感受下:
class MacroCommend { constructor() { this.commendList = [] } add(commend) { this.commendList.push(commend) } execute() { for (let i = 0, commend; commend = this.commendList[i++];) { commend.execute() } } } let openAirConCommend = { execute: function () { console.log('Open air-conditioning ') } } let openTvCommend = { execute: function () { console.log('Open TV ') } } let openSoundCommend = { execute: function () { console.log('Open sound box') } } let openQQCommend = { execute: function () { console.log('Open QQ') } } let closeDoorCommend = { execute: function () { console.log('Close door') } } let openPcCommend = { execute: function () { console.log('Open pc ') } } let commend1 = new MacroCommend() commend1.add(openTvCommend) commend1.add(openSoundCommend) let commend2 = new MacroCommend() commend2.add(closeDoorCommend) commend2.add(openPcCommend) commend2.add(openQQCommend) let macroCommend = new MacroCommend() macroCommend.add(openAirConCommend) macroCommend.add(commend1) macroCommend.add(commend2) macroCommend.execute()
运行结果:
Open air-conditioning
Open TV
Open sound box
Close door
Open pc
Open QQ
这段代码意思是: 当回家的时候,按下万能遥控execute按钮后发生的一系列操作。打开空调,打开电视、音响,关门、打开电脑、登录qq。其中有单个对象openAirConCommend、openTvCommend...,组合对象cammend1(打开电视和音响),commend2(关门、打开电脑、登录qq)。 组合模式提供了一种遍历树形结构的方案,通过调用macroCommend 组合对象的execute方法,程序会递归调用组合对象下面叶对象的execute方法。
二、用途
组合模式将对象组合成树形结构(如下图)除了表示树形结构外,组合模式的另一个好处就是通过对象的多态性,使得用户对单个对象和组合对象的使用具有一致性。
利用对象的多态性统一对待组合对象和单一对象,可以忽略组合对象和单一对象的不同。组合模式中,用户将统一的使用组合模式中的任意对象,而不需要关心它到底是组合对象,还是叶子对象。
看到这里是不是觉着上面的代码有问题啊,万一有人在叶子对象上尝试添加子对象咋整?解决方案是在叶子节点添加add方法,抛出异常
let openTvCommend = { execute: function () { console.log('Open TV ') }, add: function () { throw new Error('叶子节点不能添加子节点') } }三、总结
1、使用组合模式,叶对象和组合对象使用必须具有一致性,即拥有相同的接口。一个必要条件,对一组叶对象的操作具有一致性。
2、组合模式不是父子关系,组合模式是一种HAS-A(聚合)关系,而不是IS-A, 叶对象并不是组合对象的子类,只是具有相同的接口
3、使用职责链提高组合模式树的遍历性能。当组合模式的节点数较多时,可借助职责链模式提升性能。