例子: Extjs : Ext.CompositeElement ,Standard composite class. Creates a Ext.Element for every element in the collection.
一般面向对象语言的做法 :
按照一般面向对象语言的做法,首先要定义接口,然后composite 和 leaf 直接实现这个借口,leaf用来具体操作,composite则用来遍历,调用相应方法。 遍历 的代码每个接口方法都要重复。
javascript (extjs) 做法:
由于方法可以动态添加,则可以跳过这个限制,直接在叶子节点添加相应的操作,然后再将操作方法统一利用遍历添加到composite类。
例如:
Ext.Element 作为 leaf 有很多操作:setStyle ,setHeight ....
那么 Ext.CompositeElement 作为 composite 也应该支持相应的操作,难道按照传统语言,
将element的各个方法都实现一遍,只为了在每个实现方法中循环调用element的相应方法?!
看看extjs 怎么利用javascript 的动态特性吧。
(function(){ Ext.CompositeElement.createCall = function(proto, fnName){ if(!proto[fnName]){ proto[fnName] = function(){ return this.invoke(fnName, arguments); }; } }; for(var fnName in Ext.Element.prototype){ if(typeof Ext.Element.prototype[fnName] == "function"){ Ext.CompositeElement.createCall(Ext.CompositeElement.prototype, fnName); } }; })();
只要上述代码运行,则自动将 element 的相应方法设置到了 composite 上面。那么常规的遍历操作呢?
那就要看看invoke方法了。
invoke : function(fn, args){ var els = this.elements; for(var i = 0, len = els.length; i < len; i++) { Ext.Element.prototype[fn].apply(els[i], args); } return this; },
可见 extjs composite 模式的实现并没有 仿照传统语言将方法都手动实现在代码里,而是在element确定后,动态的添加到composite里面,并且利用统一的遍历操作来代替传统语言在每个方法的手动遍历调用。invoke 也算用到了 装饰模式,对 element 的各个方法 增强了一下算做自己的方法。(090601)
总结:javascript composite模式 是以leaf 的操作为优先,并其后动态添加到 composite ,不同于传统语言一接口优先,leaf,composite分别实现接口。
PS:组合模式理论基础:
from Pro Javascript Design Patterns
组合模式的两大好处:
1.你可以用同样的方法处理对象的集合与其中特定的对象。composite与leaf实现了同一批操作。对组和对象执行的这些操作将向下传递到所有的leaf。这样一来所有的组成对象都会执行同样的操作。在存在大批对象的情况下,这是一种非常有效的技术。藉此你可以不着痕迹的用一组对象替换一个对象。反之亦然。这有助于弱化各个对象之间的耦合。
2.他可以把一批子对象组织成树形结构,并且使整棵树可以被遍历。所有组合对象都实现了一的代码都不会对其内部实现形成依赖。
在组合对象的层次结构中有两种类型的对象:叶对象和组合对象。这是一种递归定义,但这正是组合对象有用的原因。一个组合对象有一些别的组合对象和叶对象组成。其中只有叶对象不再包含子对象。叶对象是组合对象中最基本的元素,也是各种操作的落脚点。
组合模式的使用范围:
1.存在一批组织成某种层次的对象(具体结构在开发过程中可能无法得知)。
2.希望对这批对象或其中的一部分对象实施一个操作。
组合模式优点:
组合对象擅长于对大批对象就行操作。它专为组织这类对象并把操作从一个层次向下一个层次传递而设计。藉此你可以弱化对象间的耦合并可互转换的使用一些类或实例。使得代码模块化程度更高,也更容易维护。对象之间耦合松散,可随意改变他们之间的位置,促进代码重用,有利于代码重构。在对象层次体系中添加,删除和查找节点都非常容易。
组合模式缺点:
但是如果对象层次过于大,则系统性能会受影响,每个操作实际山都是对整棵对象树的遍历操作调用。系统也越复杂。
相关探讨: