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 相关文章推荐
jQuery源码分析-01总体架构分析
Nov 14 Javascript
javascript学习笔记(二) js一些基本概念
Jun 18 Javascript
JavaScript中的Truthy和Falsy介绍
Jan 01 Javascript
jQuery实现预加载图片的方法
Mar 17 Javascript
jquery采用oop模式class类的使用示例
Jan 22 Javascript
从零学习node.js之详解异步控制工具async(八)
Feb 27 Javascript
Vee-Validate的使用方法详解
Sep 22 Javascript
bootstrap table实现合并单元格效果
Dec 24 Javascript
VuePress 静态网站生成方法步骤
Feb 14 Javascript
详解如何提升JSON.stringify()的性能
Jun 12 Javascript
如何基于JS截获动态代码
Dec 25 Javascript
基于 Vue 的 Electron 项目搭建过程图文详解
Jul 22 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动态生成虚拟现实VRML网页
2006/10/09 PHP
PHP 数组基础知识小结
2010/08/20 PHP
php验证码的制作思路和实现方法
2015/11/12 PHP
PHP设计模式之工厂方法设计模式实例分析
2018/04/25 PHP
PHP实现的猴王算法(猴子选大王)示例
2018/04/30 PHP
PHP中ltrim()函数的用法与实例讲解
2019/03/28 PHP
xtree.js 代码
2007/03/13 Javascript
js与jquery获取父级元素,子级元素,兄弟元素的实现方法
2014/01/09 Javascript
javascript遍历控件实例详细解析
2014/01/10 Javascript
浅谈jQuery异步对象(XMLHttpRequest)
2014/11/17 Javascript
JS模仿编辑器实时改变文本框宽度和高度大小的方法
2015/08/17 Javascript
分享几种比较简单实用的JavaScript tabel切换
2015/12/31 Javascript
悬浮广告方法日常收集整理
2016/03/18 Javascript
详解vue-cli之webpack3构建全面提速优化
2017/12/25 Javascript
详解单页面路由工程使用微信分享及二次分享解决方案
2019/02/22 Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
2019/10/16 Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
2019/11/29 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2永雾林渊版本开启新篇章
2020/12/22 DOTA
python输出当前目录下index.html文件路径的方法
2015/04/28 Python
名片管理系统python版
2018/01/11 Python
Python爬虫包BeautifulSoup实例(三)
2018/06/17 Python
Python中类似于jquery的pyquery库用法分析
2019/12/02 Python
Anconda环境下Vscode安装Python的方法详解
2020/03/29 Python
美国最好的钓鱼、狩猎和划船装备商店:Bass Pro Shops
2018/12/02 全球购物
June Jacobs尊积帕官网:知名的spa水疗护肤品牌
2019/03/21 全球购物
巴西最大的运动品牌:Olympikus
2020/07/14 全球购物
服装采购员岗位职责
2014/03/15 职场文书
学生安全责任书模板
2014/07/25 职场文书
个人师德师风自我剖析材料
2014/09/29 职场文书
2014年服装销售工作总结
2014/11/27 职场文书
MySQL学习总结-基础架构概述
2021/04/05 MySQL
基于Redis实现分布式锁的方法(lua脚本版)
2021/05/12 Redis
最新最全的手机号验证正则表达式
2022/02/24 Javascript
Python使用BeautifulSoup4修改网页内容
2022/05/20 Python
Java时间工具类Date的常用处理方法
2022/05/25 Java/Android
利用Apache Common将java对象池化的问题
2022/06/16 Servers