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 相关文章推荐
EasySlider 基于jQuery功能强大简单易用的滑动门插件
Jun 11 Javascript
SlideView 图片滑动(扩展/收缩)展示效果
Aug 01 Javascript
表单序列化与jq中的serialize使用示例
Feb 21 Javascript
文本域光标操作的jQuery扩展分享
Mar 10 Javascript
require.js 加载 vue组件 r.js 合并压缩的实例
Oct 14 Javascript
微信小程序 wx:key详细介绍
Oct 28 Javascript
js实现文字无缝向上滚动
Feb 16 Javascript
vue双向绑定简要分析
Mar 23 Javascript
使用bootstraptable插件实现表格记录的查询、分页、排序操作
Aug 06 Javascript
Canvas放置反弹效果随机图形(实例)
Aug 17 Javascript
JS实现数组简单去重及数组根据对象中的元素去重操作示例
Jan 05 Javascript
vue实现折线图 可按时间查询
Aug 21 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
一拳超人中怪人协会钦定! S级别最强四人!
2020/03/02 日漫
【动漫杂谈】关于《请在T台上微笑》
2020/03/03 日漫
php字符比较函数similar_text、strnatcmp与strcasecmp用法分析
2014/11/18 PHP
PHP防止图片盗用(盗链)的方法小结
2016/11/11 PHP
php 删除指定文件夹的实例讲解
2017/07/25 PHP
laravel Task Scheduling(任务调度)在windows下的使用详解
2019/10/22 PHP
再谈IE中Flash控件的自动激活 ObjectWrap
2007/03/09 Javascript
Nodejs学习笔记之Stream模块
2015/01/13 NodeJs
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
使用jQuery监听DOM元素大小变化
2016/02/24 Javascript
原生JS:Date对象全面解析
2016/09/06 Javascript
一句jQuery代码实现返回顶部效果(简单实用)
2016/12/28 Javascript
JavaScript数据结构与算法之基本排序算法定义与效率比较【冒泡、选择、插入排序】
2019/02/21 Javascript
Nodejs核心模块之net和http的使用详解
2019/04/02 NodeJs
vue中input的v-model清空操作
2019/09/06 Javascript
Vue的全局过滤器和私有过滤器的实现
2020/04/20 Javascript
JS图片懒加载技术实现过程解析
2020/07/27 Javascript
详解JavaScript自定义函数
2020/07/29 Javascript
如何在Vue.JS中使用图标组件
2020/08/04 Javascript
js前端对于大量数据的展示方式及处理方法
2020/12/02 Javascript
python多线程扫描端口示例
2014/01/16 Python
python spyder中读取txt为图片的方法
2018/04/27 Python
解决nohup重定向python输出到文件不成功的问题
2018/05/11 Python
ML神器:sklearn的快速使用及入门
2019/07/11 Python
Pytorch Tensor 输出为txt和mat格式方式
2020/01/03 Python
详解HTML5中的picture元素响应式处理图片
2018/01/03 HTML / CSS
GUESS盖尔斯法国官网:美国时尚品牌
2016/09/23 全球购物
夏威夷咖啡公司:Hawaii Coffee Company
2019/09/19 全球购物
Levi’s西班牙官方网站:李维斯,著名的牛仔裤品牌
2020/08/20 全球购物
介绍一下RMI的基本概念
2016/12/17 面试题
《钱学森》听课反思
2014/03/01 职场文书
中学教师师德承诺书
2014/05/23 职场文书
电子商务优秀毕业生求职信
2014/07/11 职场文书
自愿离婚协议书范本2016
2016/03/18 职场文书
2019年“我为祖国点赞”演讲稿(3篇)
2019/09/26 职场文书
mysql如何配置白名单访问
2021/06/30 MySQL