Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6289
  • 博文数量: 6
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-29 11:50
个人简介

多年web前端开发

文章分类
文章存档

2014年(6)

我的朋友
最近访客

分类: JavaScript

2014-05-29 14:35:02

原文地址:JS设计模式四:组合模式 作者:lovenyf


组合模式


    组合模式:把多个对象组成树状结构来表示局部与整体,使得用户可以一样的对待单个对象和对象的组合。

    1. 可以以相同的方法处理对象的集合与其中的特定子对象。组合对象与组成该对象的对象可实现同一批的操作。对组合( Composite )对象执行的操作将向下传递到所有的组成对象( constituent object ),使得所有组成对象都会执行同样的操作。

    2. 可以将对象组织成树形结构,并且使整棵树可被遍历。所有组合对象都实现一个用来获取其子对象的方法,借助该方法可以隐藏实现的细节,组织子对象,使子对象内部实现不形成依赖。

(Java 代码示例 From WikiPedia)

  1. /** "Component" */
  2. interface Graphic {
  3.  
  4.     //Prints the graphic.
  5.     public void print();
  6. }
  7.  
  8. /** "Composite" */
  9. import java.util.List;
  10. import java.util.ArrayList;
  11. class CompositeGraphic implements Graphic {
  12.  
  13.     //Collection of child graphics.
  14.     private List<Graphic> childGraphics = new ArrayList<Graphic>();
  15.  
  16.     //Prints the graphic.
  17.     public void print() {
  18.         for (Graphic graphic : childGraphics) {
  19.             graphic.print();
  20.         }
  21.     }
  22.  
  23.     //Adds the graphic to the composition.
  24.     public void add(Graphic graphic) {
  25.         childGraphics.add(graphic);
  26.     }
  27.  
  28.     //Removes the graphic from the composition.
  29.     public void remove(Graphic graphic) {
  30.         childGraphics.remove(graphic);
  31.     }
  32. }
  33.  
  34. /** "Leaf" */
  35. class Ellipse implements Graphic {
  36.  
  37.     //Prints the graphic.
  38.     public void print() {
  39.         System.out.println("Ellipse");
  40.     }
  41. }
  42.  
  43. /** Client */
  44. public class Program {
  45.  
  46.     public static void main(String[] args) {
  47.         //Initialize four ellipses
  48.         Ellipse ellipse1 = new Ellipse();
  49.         Ellipse ellipse2 = new Ellipse();
  50.         Ellipse ellipse3 = new Ellipse();
  51.         Ellipse ellipse4 = new Ellipse();
  52.  
  53.         //Initialize three composite graphics
  54.         CompositeGraphic graphic = new CompositeGraphic();
  55.         CompositeGraphic graphic1 = new CompositeGraphic();
  56.         CompositeGraphic graphic2 = new CompositeGraphic();
  57.  
  58.         //Composes the graphics
  59.         graphic1.add(ellipse1);
  60.         graphic1.add(ellipse2);
  61.         graphic1.add(ellipse3);
  62.  
  63.         graphic2.add(ellipse4);
  64.  
  65.         graphic.add(graphic1);
  66.         graphic.add(graphic2);
  67.  
  68.         //Prints the complete graphic (four times the string "Ellipse").
  69.         graphic.print();
  70.     }
  71. }


JS中的组合模式

    对于创建动态用户界面来说,组合模式可以算是为其量身定做的,因为HTML结构正好符合组合模式适用场景的结构。


    1. 存在一批组织成某种层次体系的对象。

    2. 希望对这批对象或者其中某一部分对象实施一个操作。


    组合模式擅长对大批量对象进行操作,专为组织这类对象吧操作从一个层次向下一个层次传递设计,藉此可以弱化对象间的耦合关系并且可以互换使用一些类或者实例。使代码模块化程度更高,维护容易。


    这边是JS设计模式中的比较简单的图片库实例:

首先当然是作为图片库的组合对象:


  1. function ImagesStore( id ){
  2.     this.children = [];
  3.     this.element = document.createElement("div");
  4.     this.element.id = id;
  5.     this.element.className = "imgs-store";
  6. }

  7. ImagesStore.prototype = {
  8.     constructor : ImagesStore,

  9.     add : function( child ){
  10.         this.children.push( child );
  11.         this.element.appendChild( child.getElement() );
  12.     },
  13.     
  14.     remove : function( child ){
  15.         for( var node, i=0; node = this.getChild(i); i++ ){
  16.             if( node === child ){
  17.                 this.children.splice( i, 1 );
  18.                 break;
  19.             }
  20.             this.element.removeChild( child.getElement() );
  21.         }
  22.     },

  23.     getChild : function( i ){
  24.         return this.children[i];
  25.     },

  26.     show : function(){
  27.         this.element.style.display = '';
  28.         for( var node, i=0; node = this.getChild(i); i++ ){
  29.             node.show();
  30.         }
  31.     },

  32.     hide : function(){
  33.         for( var node, i=0; node = this.getChild(i); i++ ){
  34.             node.hide();
  35.         }
  36.         this.element.style.display = 'none';
  37.     },

  38.     getElement : function(){
  39.         return this.element;
  40.     }
  41. }

    从上面的组合对象中我们可以看出,原型上的 hide 和 show 方法不单单只是对于当前的 element 进行处理,还延生到其包含的每一个叶对象上执行。这边就体现了组合模式的运行机制,一条命令在多个对象上激发复杂的或者递归的行为。在此处我们可以看到每一个对象中的element属性中都指向了该对象的实质 DOM对象,一般来说不会有什么大问题,但是需要注意的是 千万小心再将 DOM对象中放入引用 JS对象的属性,这样会导致在一些浏览器中内存泄露,部分内存无法回收。


下面便是子对象的 image 类:


  1. function ImageItem( src ){
  2.     this.element = document.createElement("img");
  3.     this.element.src = src;
  4.     this.element.className = "img-item";
  5. }

  6. ImageItem.prototype = {
  7.     constructor : ImagesStore,

  8.     add : function( child ){
  9.         throw new Error("this is image object, no add function");
  10.     },
  11.     
  12.     remove : function( child ){
  13.         throw new Error("this is image object, no remove function");
  14.     },

  15.     getChild : function( i ){
  16.         throw new Error("this is image object, no getChild function");
  17.     },

  18.     show : function(){
  19.         this.element.style.display = '';
  20.     },

  21.     hide : function(){
  22.         this.element.style.display = 'none';
  23.     },

  24.     getElement : function(){
  25.         return this.element;
  26.     }
  27. }

那么对于一个图片库实现起来也就非常简单了,


  1. var store = new ImagesStore("first");
  2. store.add( new ImageItem("/img/1.jpg") );
  3. store.add( new ImageItem("/img/2.jpg") );

    再在对应的DOM中插入store.element 即可以使用 store.show() 等方法进行控制。并且每个对象之间的耦合非常松散,简单的操作处理复杂的结果。


    使用组合模式组织起来的对象具有出色的层次结构,每当对顶层组合对象执行一个操作的时候,实际上是在对整个结构进行深度优先的节点搜索。但是这些优点都是用操作的代价换取的,比如顶级每执行一次 store.show 实际的操作就是整一颗树形结构的节点均遍历执行一次。


    简单地说,组合模式是将一批子对象组织为树形结构,一条顶层的命令会在操作树中所有的对象。提高了代码的模块化程度,对于动态的HTML界面具有很强的适用性。


阅读(184) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~