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. Linux打包命令 - tar

    上一篇文章谈到的命令大多仅能针对单一文件来进行压缩,虽然 gzip 与 bzip2 也能够针对目录来进行压缩, 不过,这两个命令对目录的压缩指的是『将目录内的所有文件 "分别" 进 ...

  2. EBS-子库存转移和物料搬运单区别

    FROM:http://bbs.erp100.com/forum.php?mod=viewthread&tid=261550&extra=page%3D7 EBS-子库存转移和物料搬运 ...

  3. 史上最强Spring mvc入门

    一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 1 2 3 4 5 6 ...

  4. 【39】FlexboxLayout使用介绍

    FlexboxLayout介绍: Flexbox 也称为弹性盒子模型 或伸缩盒子模型,广泛用于前端开发,做过前端 web 的都知道Bootstrap 中有一套强大的 CSS Grid网格样式.Boot ...

  5. asp.net 下的中文分词检索工具 - jieba.net

    jieba是python下的一个检索库, 有人将这个库移植到了asp.net 平台下, 完全可以替代lucene.net以及盘古分词的搭配 之所以写这个, 其实是因为昨天面试时, 被问到网站的关键字检 ...

  6. Mac环境svn的使用

    在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境.在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还 ...

  7. JQuery(一)---- JQ的选择器,属性,节点,样式,函数等操作详解

    JQuery的基本概念 JQuery是一个javascript库,JQuery凭借着简洁的语法和跨平台的兼容性,极大的简化了js操作DOM.处理事件.执行动画等操作.JQuery强调的理念是:'wri ...

  8. JAVA 平台

    由Java虚拟机和Java核心类所构成.它为纯Java程序提供了统一的编程接口,而不管下层操作系统是什么. 目录 1Java术语 2移动平台 3桌面应用平台 4企业级平台 5JRE的成分     1J ...

  9. Day9 操作系统介绍

    操作系统简介(转自林海峰老师博客介绍)

  10. Mac 下实现 pyenv/virtualenv 与 Anaconda 的兼容

    http://blog.csdn.net/vencent7/article/details/76849849 自己一直用的 pyenv 和 pyenv-virtualenv 管理不同的 python ...