组合模式
组合模式:把多个对象组成树状结构来表示局部与整体,使得用户可以一样的对待单个对象和对象的组合。
1. 可以以相同的方法处理对象的集合与其中的特定子对象。组合对象与组成该对象的对象可实现同一批的操作。对组合( Composite )对象执行的操作将向下传递到所有的组成对象( constituent object ),使得所有组成对象都会执行同样的操作。
2. 可以将对象组织成树形结构,并且使整棵树可被遍历。所有组合对象都实现一个用来获取其子对象的方法,借助该方法可以隐藏实现的细节,组织子对象,使子对象内部实现不形成依赖。
(Java 代码示例 From WikiPedia)
-
/** "Component" */
-
interface Graphic {
-
-
//Prints the graphic.
-
public void print();
-
}
-
-
/** "Composite" */
-
import java.util.List;
-
import java.util.ArrayList;
-
class CompositeGraphic implements Graphic {
-
-
//Collection of child graphics.
-
private List<Graphic> childGraphics = new ArrayList<Graphic>();
-
-
//Prints the graphic.
-
public void print() {
-
for (Graphic graphic : childGraphics) {
-
graphic.print();
-
}
-
}
-
-
//Adds the graphic to the composition.
-
public void add(Graphic graphic) {
-
childGraphics.add(graphic);
-
}
-
-
//Removes the graphic from the composition.
-
public void remove(Graphic graphic) {
-
childGraphics.remove(graphic);
-
}
-
}
-
-
/** "Leaf" */
-
class Ellipse implements Graphic {
-
-
//Prints the graphic.
-
public void print() {
-
System.out.println("Ellipse");
-
}
-
}
-
-
/** Client */
-
public class Program {
-
-
public static void main(String[] args) {
-
//Initialize four ellipses
-
Ellipse ellipse1 = new Ellipse();
-
Ellipse ellipse2 = new Ellipse();
-
Ellipse ellipse3 = new Ellipse();
-
Ellipse ellipse4 = new Ellipse();
-
-
//Initialize three composite graphics
-
CompositeGraphic graphic = new CompositeGraphic();
-
CompositeGraphic graphic1 = new CompositeGraphic();
-
CompositeGraphic graphic2 = new CompositeGraphic();
-
-
//Composes the graphics
-
graphic1.add(ellipse1);
-
graphic1.add(ellipse2);
-
graphic1.add(ellipse3);
-
-
graphic2.add(ellipse4);
-
-
graphic.add(graphic1);
-
graphic.add(graphic2);
-
-
//Prints the complete graphic (four times the string "Ellipse").
-
graphic.print();
-
}
-
}
JS中的组合模式
对于创建动态用户界面来说,组合模式可以算是为其量身定做的,因为HTML结构正好符合组合模式适用场景的结构。
1. 存在一批组织成某种层次体系的对象。
2. 希望对这批对象或者其中某一部分对象实施一个操作。
组合模式擅长对大批量对象进行操作,专为组织这类对象吧操作从一个层次向下一个层次传递设计,藉此可以弱化对象间的耦合关系并且可以互换使用一些类或者实例。使代码模块化程度更高,维护容易。
这边是JS设计模式中的比较简单的图片库实例:
首先当然是作为图片库的组合对象:
-
function ImagesStore( id ){
-
this.children = [];
-
this.element = document.createElement("div");
-
this.element.id = id;
-
this.element.className = "imgs-store";
-
}
-
-
ImagesStore.prototype = {
-
constructor : ImagesStore,
-
-
add : function( child ){
-
this.children.push( child );
-
this.element.appendChild( child.getElement() );
-
},
-
-
remove : function( child ){
-
for( var node, i=0; node = this.getChild(i); i++ ){
-
if( node === child ){
-
this.children.splice( i, 1 );
-
break;
-
}
-
this.element.removeChild( child.getElement() );
-
}
-
},
-
-
getChild : function( i ){
-
return this.children[i];
-
},
-
-
show : function(){
-
this.element.style.display = '';
-
for( var node, i=0; node = this.getChild(i); i++ ){
-
node.show();
-
}
-
},
-
-
hide : function(){
-
for( var node, i=0; node = this.getChild(i); i++ ){
-
node.hide();
-
}
-
this.element.style.display = 'none';
-
},
-
-
getElement : function(){
-
return this.element;
-
}
-
}
从上面的组合对象中我们可以看出,原型上的 hide 和 show 方法不单单只是对于当前的 element 进行处理,还延生到其包含的每一个叶对象上执行。这边就体现了组合模式的运行机制,一条命令在多个对象上激发复杂的或者递归的行为。在此处我们可以看到每一个对象中的element属性中都指向了该对象的实质 DOM对象,一般来说不会有什么大问题,但是需要注意的是 千万小心再将 DOM对象中放入引用 JS对象的属性,这样会导致在一些浏览器中内存泄露,部分内存无法回收。
下面便是子对象的 image 类:
-
function ImageItem( src ){
-
this.element = document.createElement("img");
-
this.element.src = src;
-
this.element.className = "img-item";
-
}
-
-
ImageItem.prototype = {
-
constructor : ImagesStore,
-
-
add : function( child ){
-
throw new Error("this is image object, no add function");
-
},
-
-
remove : function( child ){
-
throw new Error("this is image object, no remove function");
-
},
-
-
getChild : function( i ){
-
throw new Error("this is image object, no getChild function");
-
},
-
-
show : function(){
-
this.element.style.display = '';
-
},
-
-
hide : function(){
-
this.element.style.display = 'none';
-
},
-
-
getElement : function(){
-
return this.element;
-
}
-
}
那么对于一个图片库实现起来也就非常简单了,
-
var store = new ImagesStore("first");
-
store.add( new ImageItem("/img/1.jpg") );
-
store.add( new ImageItem("/img/2.jpg") );
再在对应的DOM中插入store.element 即可以使用 store.show() 等方法进行控制。并且每个对象之间的耦合非常松散,简单的操作处理复杂的结果。
使用组合模式组织起来的对象具有出色的层次结构,每当对顶层组合对象执行一个操作的时候,实际上是在对整个结构进行深度优先的节点搜索。但是这些优点都是用操作的代价换取的,比如顶级每执行一次 store.show 实际的操作就是整一颗树形结构的节点均遍历执行一次。
简单地说,组合模式是将一批子对象组织为树形结构,一条顶层的命令会在操作树中所有的对象。提高了代码的模块化程度,对于动态的HTML界面具有很强的适用性。
阅读(6187) | 评论(0) | 转发(1) |