javascript设计模式之组合模式

介绍

组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式。使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为。这可以简化粘合性代码,使其更容易维护,而那些复杂行为则被委托给各个对象。

组合模式的好处:

  • 1 你可以用同样的方法处理对象的集合与其中的特定子对象。
  • 2 它可以用来把一批子对象组织成树形结构,并且使整棵树都可以被遍历。

正文

组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。

常见的场景有asp.net里的控件机制(即control里可以包含子control,可以递归操作、添加、删除子control),类似的还有DOM的机制,一个DOM节点可以包含子节点,不管是父节点还是子节点都有添加、删除、遍历子节点的通用功能。所以说组合模式的关键是要有一个抽象类,它既可以表示子元素,又可以表示父元素。

场景

    组合模式场景:   -->公司
-->财务部门
-->张一
-->张二
-->张三 -->销售部门
-->张四
-->张五
-->张六
实际任务是具体落实到人上去实施的,也就是说
只有人才具有具体的方法实现

<!DOCTYPE html>
<html>
<head>
<script src="./commonUtil.js" type="text/javascript" charset="utf-8" ></script> <title>组合模式</title>
</head>
<body>
<script>
/*
组合模式场景: -->公司
-->财务部门
-->张一
-->张二
-->张三 -->销售部门
-->张四
-->张五
-->张六
实际任务是具体落实到人上去实施的,也就是说
只有人才具有具体的方法实现
*/ //定义一个公司
var Orgnazation = function(name){
this.name = name ;
this.departments= []; };
Orgnazation.prototype = {
constructor: Orgnazation,
addDepts : function(childOrgnazation){
this.departments.push(childOrgnazation);
//链式调用
return this;
},
getDepts: function(){
return this.departments;
} }; //定义一个部门
var Department = function(name){
this.name = name ;
this.persons = [];
};
Department.prototype = {
constructor:Department,
addPersons : function (childPerson){
this.persons.push(childPerson);
return this;
},
getPersons: function(){
return this.persons;
}
}; //定义一个人
var Person = function(name){
this.name = name ;
};
Person.prototype ={
constructor:Person,
hardworking:function(name){
document.write(this.name + "....好好上班!");
},
sleeping: function(name){
document.write(this.name + "....好好休息!"); }
}; /*需求:1、实例化上述情景,2、叫张三好好工作*/
var org = new Orgnazation("华为");
var dept1 = new Department("财务部门");
var dept2 = new Department("销售部门");
var p1 = new Person("张1");
var p2 = new Person("张2");
var p3 = new Person("张3");
var p4 = new Person("张4");
var p5 = new Person("张5");
var p6 = new Person("张6"); dept1.addPersons(p1).addPersons(p2).addPersons(p3);
dept2.addPersons(p4).addPersons(p5).addPersons(p6);
org.addDepts(dept1).addDepts(dept2); for(var i =0 , depts = org.getDepts(); i <depts.length ; i ++ ){
for (var j = 0, persons = depts[i].getPersons(); j < persons.length; j++){
if (persons[j].name =="张3") {
persons[j].hardworking();
};
} }
/*
上述方法完全是面向对象的方法,实现的上述需求,如果要给变功能(比如说,财务部全体放假,整个公司好好休息!增加一个新部门,在好好工作。。。。。),怎要动怎么for循环,这样不是我们想要的,如果我们引入组合模式,是不是能解决效果呢? 直接 org.hardworking("华为")
*/ </script> </body>
</html>

组合模式的使用场景:

    1 存在一批组织成某种层次体系的对象
2 希望对这批对象或其中的一部分对象实施一个操作。
组合模式的特点:
1 组合模式中只有两种类型对象:组合对象、叶子对象
2 这两种类型都实现同一批接口
3 一般我们会在组合对象中调用其方法并隐式调用"下级对象"的方法(这里我们一般采用递归的形式去做)
*/ /*
组合模式场景: -->公司
-->北京分公司
-->财务部门
-->张一
-->张二
-->张三 -->销售部门
-->张四
-->张五
-->张六
-->南京分公司
-->开发部门
-->张7
-->张8
-->张9 -->法务部门
-->张10
-->张11
-->张12 实际任务是具体落实到人上去实施的,也就是说
只有人才具有具体的方法实现

<!DOCTYPE html>
<html>
<head>
<script src="./commonUtil.js" type="text/javascript" charset="utf-8" ></script> <title>组合模式2</title>
</head>
<body>
<script> /*
组合模式的使用场景:
1 存在一批组织成某种层次体系的对象
2 希望对这批对象或其中的一部分对象实施一个操作。
组合模式的特点:
1 组合模式中只有两种类型对象:组合对象、叶子对象
2 这两种类型都实现同一批接口
3 一般我们会在组合对象中调用其方法并隐式调用"下级对象"的方法(这里我们一般采用递归的形式去做)
*/ /*
组合模式场景: -->公司
-->北京分公司
-->财务部门
-->张一
-->张二
-->张三 -->销售部门
-->张四
-->张五
-->张六
-->南京分公司
-->开发部门
-->张7
-->张8
-->张9 -->法务部门
-->张10
-->张11
-->张12 实际任务是具体落实到人上去实施的,也就是说
只有人才具有具体的方法实现
*/ //定义接口
var CompositeInterface = new XGP.Interface("CompositeInterface", ["addChild","getChild"]);
var LeafInterface = new XGP.Interface("LeafInterface", ["hardworking","sleeping"]); // 首先建立组合对象
var Composite = function(name){
this.name = name ;
this.type = "Composite"; //说明对象的类型为(组合对象)
this.children = []; //承装孩子的数组
}; //建立叶子对象
var Leaf = function(name){
this.name = name ;
this.type = "Leaf";
}; //实现同一批接口
Composite.prototype = {
constructor: Composite,
addChild:function(child){
this.children.push(child);
return this;
}, //难点!!!!
getChild:function(name){
//接收叶子对象
var elments =[]; var pushLeaf = function(item){
if(item.type ==="Composite"){
item.children.each(arguments.callee);//看是否是Composite还是Leaf;
}else{
elments.push(item);//直接添加到叶子对象集合
}
}); if (name && this.name !== name) {//根据name ,让name下的Compsite的所有Leaf去执行操作
this.children.each(function(item){
//如果是2级节点名称---北京分公司,南京分公司
if (item.name === name && item.type =="Composite") {
item.children.each(pushLeaf); };
//如果是3级,4级。。。。N级
if (item.name !== name && item.type =="Composite") {
item.children.each(arguments.callee);
}; //如果传递的就是叶子节点
if (item.name == name && item.type =="Leaf") {
elments.push(item);
};
}); }else{//不传名字,则整个公司的所有类型的leaf 类型执行操作
//Array.prototype.each()方法----添加到commomUtil.js
this.children.each(pushLeaf); //直接抽取到pushLeaf函数中
};
},
hardworking: function(name){
//对于Composite类型的对象,要先获得其下面所有的Leaf对象
var leafObjects = this.getChild(name);
for (var i = 0; i < leafObjects.length; i++) {
leafObjects[i].hardworking();
};
},
sleeping: function(){
//对于Composite类型的对象,要先获得其下面所有的Leaf对象
var leafObjects = this.getChild(name);
for (var i = 0; i < leafObjects.length; i++) {
leafObjects[i].sleeping();
};
} }; Leaf.prototype = {
constructor: Leaf,
addChild:function(child){
throw new Error("this method is disable...");
},
getChild:function(name){
if(this.name = name ){
return this;
};
return null;
},
hardworking: function(){
document.write(this.name + "....好好上班!"); },
sleeping: function(){
document.write(this.name + "....好好休息!");
} }; //测试数据
var org = new CompositeInterface("华为");
var suborg1 = new CompositeInterface("北京分公司");
var suborg2 = new CompositeInterface("南京分公司");
var dept1 = new CompositeInterface("财务部门");
var dept2 = new CompositeInterface("销售部门");
var dept3 = new CompositeInterface("开发部门");
var dept4 = new CompositeInterface("法务部门");
var p1 = new Leaf("张1");
var p2 = new Leaf("张2");
var p3 = new Leaf("张3");
var p4 = new Leaf("张4");
var p5 = new Leaf("张5");
var p6 = new Leaf("张6");
var p7 = new Leaf("张7");
var p8 = new Leaf("张8");
var p9 = new Leaf("张9");
var p10 = new Leaf("张10");
var p11 = new Leaf("张11");
var p12 = new Leaf("张12"); dept1.addChild(p1).addChild(p2).addChild(p3);
dept2.addChild(p4).addChild(p5).addChild(p6);
dept3.addChild(p7).addChild(p8).addChild(p9);
dept2.addChild(p10).addChild(p11).addChild(p12);
suborg1.addChild(dept1).addChild(dept2);
suborg2.addChild(dept3).addChild(dept4);
org.addChild(suborg1).addChild(suborg2);
//让公司整个员工都去努力工作
org.hardworking();
document.write("<Br>--------------------<Br>");
org.hardworking("北京分公司");
document.write("<Br>--------------------<Br>");
org.hardworking("南京分公司");
document.write("<Br>--------------------<Br>");
org.hardworking("法务部门");
document.write("<Br>--------------------<Br>");
org.hardworking("张5");
</script> </body>
</html>

总结

组合模式的使用场景非常明确:

你想表示对象的部分-整体层次结构时;

你希望用户忽略组合对象和单个对象的不同,用户将统一地使用组合结构中的所有对象(方法)

另外该模式经常和装饰者一起使用,它们通常有一个公共的父类(也就是原型),因此装饰必须支持具有add、remove、getChild操作的 component接口。

参考: https://github.com/tcorral/Design-Patterns-in-Javascript/blob/master/Composite/index.html

http://www.cnblogs.com/TomXu/archive/2012/04/12/2435530.html

版权声明:本文为小平果原创文章,转载请注明:http://blog.csdn.net/i10630226

JavaScript设计模式之----组合模式的更多相关文章

  1. 再起航,我的学习笔记之JavaScript设计模式15(组合模式)

    组合模式 组合模式(Composite): 又称部分-整体模式,将对象组合成树形结构以表示"部分整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 如果有一个 ...

  2. JavaScript设计模式(5)-组合模式

    组合模式 1. 适合使用组合模式的条件: 存在一批组织成某种层次体系的对象,如树形结构(具体的结构在开发期间可能无法得知) 希望对这批对象或其中的一部分对象实施一个相同的操作 2. 注意点: 组合对象 ...

  3. JavaScript设计模式-14.组合模式实现

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. JavaScript设计模式-13.组合模式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. 从ES6重新认识JavaScript设计模式(三): 建造者模式

    1 什么是建造者模式? 建造者模式(Builder)是将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示. 建造者模式的特点是分步构建一个复杂的对象,可以用不同组合或顺序建造出不 ...

  6. C#设计模式(10)——组合模式(Composite Pattern)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  7. c++设计模式15 --组合模式

    今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...

  8. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  9. C#设计模式(10)——组合模式(Composite Pattern)(转)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

随机推荐

  1. PS 滤镜——素描算法(二)

    利用另外一种算法完成素描特效的生成. %%% Sketch clc; clear all; Image=imread('4.jpg'); Image=double(Image); [row,col,l ...

  2. ASI与AFN网络请求的的比较

    对比 ASI AFN 更新状态 2012年10月份,已经停止更新 持续更新中,目前已更新至3.0版 介绍 ASI的直接操作对象ASIHTTPRequest,是一个实现了了NSCopying协议的NSO ...

  3. The table name must be enclosed in double quotation marks or sqare bracket while accessing EXCEL by

      1  Preface DB Query Analyzer is presented by Master Gen feng, Ma from Chinese Mainland. It has Eng ...

  4. CF633G

    题目大意: 给你一棵树,根节点为1 有2种操作,第一种是给u节点所在的子树的所有节点的权值+x 第二种是询问,假设v是子树u中的节点,有多少种质数满足av = p + m·k 做法:维护子树信息显然d ...

  5. 关于linux防火墙

    1.防火墙是什么:防火墙就是用于实现Linux下访问控制的功能的,它分为硬件的或者软件的防火墙两种.无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘.而我们的任务就是需要去定义到底防火墙如何工作 ...

  6. 关闭ipv6的方法

    公司研发反应,几台机器开了一些端口,但是访问一直不通. 检查后发现,发现服务开启的是ipv6的端口,所有首先想到的办法就是关闭ipv6. 关闭ipv6的方法有两种: 第一个是在内核配置文件修改配置(p ...

  7. ubuntu10.04 安装oracle server 版 笔记

    1:从oracle 官网下载oracle 10g ,然后解压出一个database文件夹. 2 :创建RedHat的版本声明文件[默认ubuntu无法通过oracle 的检查] 在/etc/redha ...

  8. 爬虫初探--PHP

    我有收藏的cms网站,偶尔会下载一些资源,老司机都懂的:-D.然后有一次好几天没上,堆了好些没弄,心想:cao,这好麻烦啊,能不能写个脚本自动帮我搞?然后忽然就想到,这是不是就是所谓的爬虫呢?心中一阵 ...

  9. java之jsp实现动态网页

    动态页面,说白了,就是根据一定的信息(条件)去改变呈现给用户的内容. 而这里所提到的一定的信息,通常就是指,在一个表单中用户所输入的信息. 先来看一个我们常见的用户登录界面吧. 在这里我们可以看到一共 ...

  10. C#本质论笔记

    第一章 C#概述 1.1 Helo,World 学习一种新语言最好的办法就是动手写程序.        C#编译器创建的.exe程序是一个程序集(Assembly),我们也可以创建能由另一个较大的程序 ...