14-JavaScript设计模式——组合模式

来源:互联网 发布:苹果cms收费采集 编辑:程序博客网 时间:2024/06/05 05:52

组合模式:用于处理一批具有树形结构的对象的模式。

如:

-> 公司

-> 财务部门

-> 张一

-> 张二

-> 张三

-> 销售部门

-> 张四

-> 张五

-> 张六

对于以上的树形结构,我们要对这批对象或其中一部分对象实施一个操作,可以不采用设计模式来完成,但是存在一个问题,假如需求发生变化,需要增加一个新的层级结构,那么程序的可维护性和可扩展性会很差,那么我们可以用组合模式来解决这个问题。


观察以上的树形结构,是不是和文件目录结构很像?在文件目录结构中,只存在两种对象:文件夹和文件。那么“公司”和“部门”其实都相当于文件夹,张一、张二 等相当于文件,组合模式就是利用这一特点来处理树形结构的。


组合模式的特点:

1、组合模式中只有两种类型的对象:组合对象(文件夹)、叶子对象(文件);

2、这两种类型都实现同一批接口;

3、一般我们会在组合对象中调用其方法并隐式的调用“下级对象”的方法(一般采用 递归)


// 建立接口var CompositeInterface = new JG.Interface('CompositeInterface', ['addChild', 'getChild']);var LeafInterface = new JG.Interface('LeafInterface', ['hardworking', 'sleeping']);// 组合对象var Composite = function(name){this.name = name;this.type = 'Composite';this.children = [];};Composite.prototype = {constructor : Composite,addChild : function(child){this.children.push(child);return this; // 链式编程},getChild : function(name){// 这个方法是关键// 接收叶子对象的数组var elements = [];var pushLeaf = function(item){if (item.type === 'Composite') {item.children.forEach(arguments.callee);}else if (item.type === 'Leaf') {elements.push(item);}}if (name && this.name !== name) {this.children.forEach(function(item){if (item.name === name && item.type === 'Composite') {item.children.forEach(pushLeaf);}if (item.name !== name && item.type === 'Composite') {item.children.forEach(arguments.callee);}if (item.name === name && item.type === 'Leaf') {elements.push(item);}});}else{// 如果没有传递name,则获得所有的Leaf(叶子类型)对象this.children.forEach(pushLeaf);}return elements;},hardworking : function(name){// 得到所有的Leaf(叶子类型)对象var childObjects = this.getChild(name);for (var i = 0; i < childObjects.length; i++) {childObjects[i].hardworking();}},sleeping : function(name){// 得到所有的Leaf(叶子类型)对象var childObjects = this.getChild(name);for (var i = 0; i < childObjects.length; i++) {childObjects[i].sleeping();}}};// 叶子对象var Leaf = function(name){this.name = name;this.type = 'Leaf';};Leaf.prototype = {constructor : Leaf,addChild : function(child){throw new Error('the final child addChild method is disabled...');},getChild : function(name){if (this.name === name) {return this;}return null;},hardworking : function(name){document.write(this.name + '...努力工作!<br>');},sleeping : function(name){document.write(this.name + '...努力睡觉!<br>');}};// 测试// 创建一批叶子对象var z1 = new Leaf('张一');var z2 = new Leaf('张二');var z3 = new Leaf('张三');var z4 = new Leaf('张四');var z5 = new Leaf('张五');var z6 = new Leaf('张六');// 创建组合对象(部门)var dept1 = new Composite('财务部门');var dept2 = new Composite('销售部门');// 为部门添加员工dept1.addChild(z1).addChild(z2).addChild(z3);dept2.addChild(z4).addChild(z5).addChild(z6);// 创建组合对象(公司)var org = new Composite('中国有限公司');// 为公司添加部门org.addChild(dept1).addChild(dept2);// 获得全部员工var arr = org.getChild();arr.forEach(function(item){  document.write(item.name + '<br>');});/*结果:张一张二张三张四张五张六*/// 让销售部门的所有员工努力工作org.hardworking('销售部门');/*结果:张四...努力工作!张五...努力工作!张六...努力工作!*/// 让财务部门的所有员工努力睡觉org.sleeping('财务部门');/*结果:张一...努力睡觉!张二...努力睡觉!张三...努力睡觉!*/



原创粉丝点击