JavaScript 设计模式之组合模式解析


Posted in Javascript onApril 09, 2010

怎么说呢?!就像是动物(组合对象)一样,当它生下后代(叶对象)时,它的后代就有了某种功能(比如:挖洞,听力好等等);也像是一棵树,它有一个根(组合对象)然后是从这个棵树向外冒出的其他枝杆(组合对象)以及从这些枝杆又向外长的叶子(叶对象)。换句话说,就是当祖先已经有了,那么只要从这个祖先衍生出来的其他孩子(包括这个祖先下的其他组合对象)已经就具备了某种功能,看上去貌似又有些像是继承。“组合模式”在组合对象的层次体系中有两种类型的对象:叶对象和组合对象。组合模式擅长于对大批对象进行操作。
“组合模式”就是在做一个项目的时候,我们要把在这个项目中即将出现的方法都在组合对象中定义(包括叶对象中的方法),而它们的叶对象将会继承组合对象。当组合对象被实例化后其叶对象的方法也相应地被实例化了。可能我说的有些乱,下面就用一个例子来说明吧。
“组合模式”是一种专为创建Web上的动态用户界面而量身定制的模式。使用这种模式,可以用一条命令在多个对象上激发复杂的或递归的行为。
使用“组合模式”可以为我们带来两大好处:
1、可以用同样的方法处理对象的集合与其中的特定子对象。
2、可以用来把一批子对象组织成树形结构,并且使整棵树都可以被遍历。
只有同时具备以下两个条件进才适合使用组合模式:
1、存在一批组织成某处层次体系的对象(具体结构可能在开发期间无法知道)。
2、希望对这批对象或其中的一部分对象实话一个操作。
下面看一下示例:
具体要求是做一个图片库且可以有选择地隐藏或显示图片库的特定部分。这可能是单独图片,也可能是图片库。现在就需要两个类来完成这个功能:用作图片库的组合对象类和用于图片本身的叶对象类,代码如下:
在上面的代码中,首先定义的是组合对象类和叶对象类应该实现的接口。除了常规的组合远景一分钱上,这些类要怕硬欺软 操作只包括hide和show。接下来我们定义叶对象。叶对象实现hide和show,代码如下:

var Composite = new Interface('Composite', ['add', 'remove', 'getChild']); // 检查组合对象Composite应该具备的方法 
var GalleryItem = new Interface('GalleryItem', ['hide', 'show']); // 检查组合对象GalleryItem应该具备的方法 
// DynamicGallery Class 
var DynamicGallery = function(id){    // 实现Composite,GalleryItem组合对象类 
    this.children = [];     this.element = document.createElement('div'); 
    this.element.id = id; 
    this.element.className = 'dynamic-gallery'; 
} 
DynamicGallery.prototype = { 
    // 实现Composite组合对象接口 
    add : function(child){ 
        Interface.ensureImplements(child, Composite, DynamicGallery); 
        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]; 
    }, 
    // 实现DynamicGallery组合对象接口 
    hide : function(){ 
        for(var node, i = 0; node = this.getChild(i); i++){ 
            node.hide(); 
        } 
        this.element.style.display = 'none'; 
    }, 
    show : functioln(){ 
        this.element.style.display = 'block'; 
        for(var node, i = 0; node = getChild(i); i++){ 
            node.show(); 
        } 
    }, 
    // 帮助方法 
    getElement : function(){ 
        return this.element; 
    } 
}

以下是设置叶对象的相应方法:
// GalleryImage class 
var GalleryImage = function(src){    // 实现Composite和GalleryItem组合对象中所定义的方法 
    this.element = document.createElement('img'); 
    this.element.className = 'gallery-image'; 
    this.element.src = src; 
} 
GalleryImage.prototype = {     // 实现Composite接口 
    // 这些是叶结点,所以我们不用实现这些方法,我们只需要定义即可 
    add : function(){}, 
    remove : function(){}, 
    getChild : function(){}, 
    // 实现GalleryItem接口 
    hide : function(){ 
        this.element.style.display = 'none'; 
    }, 
    show : function(){ 
        this.element.style.display = ''; 
    }, 
    // 帮助方法 
    getElement : function(){ 
        return this.element; 
    } 
}

这是一个演示组合模式的工作方式的例子。每个类都很简单,但由于有了这样一种层次体系,我们就可以执行一些复杂操作。GalleryImage类的构造函数会创建一个image元素。这个类定义中的其余部分由空的组合对象方法(因为这是叶结点)和GalleryItem要求的操作组成。现在我们可以使用这两个类来管理图片:
var topGallery = new DynamicGallery('top-gallery'); 
topGallery.add(new GalleryImage('/img/image-1.jpg')); 
topGallery.add(new GalleryImage('/img/image-2.jpg')); 
topGallery.add(new GalleryImage('/img/image-3.jpg')); 
var vacationPhotos = new DyamicGallery('vacation-photos'); 
for(var i = 0, i < 30; i++){ 
    vacationPhotos.add(new GalleryImage('/img/vac/image-' + i + '.jpg')); 
} 
topGallery.add(vacationPhotos); 
topGallery.show(); 
vacationPhotos.hide();

组合模式之利,使用组合模式,简单的操作也能产生复杂的结果。不必编写大师手工遍历数组或其他数据结构的粘合代码,只需对最顶层的对象执行操作,主每一个子对象自己传递这个操作即可。这对于那些再三执行的操作尤其有用。在组合模式中,各个对象之间的耦合非常松散。每当对顶层组合对象执行一个操作时,实际上是在对整个结构进行尝试优先的搜索以查找节点。
组合模式之弊,由于对组合模式调用的任何操作都会被颇佳北至 它的所有子对象,如果这个层次体系很大的话,系统的性能将会受到影响。
Javascript 相关文章推荐
推荐一些非常不错的javascript学习资源站点
Aug 29 Javascript
jquery-syntax动态语法着色示例代码
May 14 Javascript
JQuery实现可直接编辑的表格
Apr 16 Javascript
JS使用eval()动态创建变量的方法
Jun 03 Javascript
BootStrap智能表单实战系列(七)验证的支持
Jun 13 Javascript
微信js-sdk上传与下载图片接口用法示例
Oct 12 Javascript
JSON 必知必会 观后记
Oct 27 Javascript
漂亮实用的页面loading(加载)封装代码
Feb 03 Javascript
react-redux中connect()方法详细解析
May 27 Javascript
在vue-cli中组件通信的方法
Dec 16 Javascript
Vue props用法详解(小结)
Jul 03 Javascript
Node.js console控制台简单用法分析
Jan 04 Javascript
跟着Jquery API学Jquery之一 选择器
Apr 07 #Javascript
基于JQuery的cookie插件
Apr 07 #Javascript
JQuery为textarea添加maxlength属性的代码
Apr 07 #Javascript
JavaScript和JQuery实用代码片段(一)
Apr 07 #Javascript
jquery 学习笔记一
Apr 07 #Javascript
ext jquery 简单比较
Apr 07 #Javascript
jQuery asp.net 用json格式返回自定义对象
Apr 07 #Javascript
You might like
PHP,ASP.JAVA,JAVA代码格式化工具整理
2010/06/15 PHP
PHP下利用header()函数设置浏览器缓存的代码
2010/09/01 PHP
php事务处理实例详解
2014/07/11 PHP
php中使用Ajax时出现Error(c00ce56e)的详细解决方案
2014/11/03 PHP
php技巧小结【推荐】
2017/01/19 PHP
解决form中action属性后面?传递参数 获取不到的问题
2017/07/21 PHP
php写app用的框架整理
2019/09/29 PHP
javascript 显示当前系统时间代码
2009/12/28 Javascript
Js组件的一些写法
2010/09/10 Javascript
js 分页全选或反选标识实现代码
2011/08/09 Javascript
使用iframe window的scroll方法控制iframe页面滚动
2014/03/05 Javascript
html文档中的location对象属性理解及常见的用法
2014/08/13 Javascript
jQuery实现无限往下滚动效果代码
2016/04/16 Javascript
JavaScript获取URL中参数querystring的方法详解
2016/10/11 Javascript
jQuery实现滚动条滚动到子元素位置(方便定位)
2017/01/08 Javascript
详解jquery validate实现表单验证 (正则表达式)
2017/01/18 Javascript
angular.JS实现网页禁用调试、复制和剪切
2017/03/31 Javascript
手动下载Chrome并解决puppeteer无法使用问题
2018/11/12 Javascript
node.js连接mysql与基本用法示例
2019/01/05 Javascript
JavaScript解析JSON数据示例
2019/07/16 Javascript
vue分页插件的使用方法
2019/12/25 Javascript
详细分析React 表单与事件
2020/07/08 Javascript
[02:40]DOTA2殁境神蚀者 英雄基础教程
2013/11/26 DOTA
django 开发忘记密码通过邮箱找回功能示例
2018/04/17 Python
python scipy卷积运算的实现方法
2019/09/16 Python
Python 列表的清空方式
2020/01/13 Python
Python loguru日志库之高效输出控制台日志和日志记录
2020/03/07 Python
Python数据可视化常用4大绘图库原理详解
2020/10/23 Python
斯凯奇澳大利亚官网:SKECHERS澳大利亚
2018/03/31 全球购物
外语系毕业生找工作的求职信
2013/11/28 职场文书
世界水日宣传活动总结
2015/02/09 职场文书
装修公司管理制度
2015/08/05 职场文书
领导干部学习三严三实心得体会
2016/01/05 职场文书
Ajax常用封装库——Axios的使用
2021/05/08 Javascript
基于Redis过期事件实现订单超时取消
2021/05/08 Redis
python 对图片进行简单的处理
2021/06/23 Python