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. boost::this_thread::sleep_for()死锁

    boost::this_thread::sleep_for()会死锁 (金庆的专栏) 发现睡眠1ms很容易死锁.boost::this_thread::sleep_for(boost::chrono: ...

  2. EBS form 之间跳转实现(form 关闭)

    实现 form CUXOMWB 使用 app_navigate.execute 打开 form CUXOEXPRAVA :然后 FROM CUXOEXPRAVA 上点击按钮 跳回from CUXOMW ...

  3. Linux IPC - Shared memory

    http://blog.163.com/muren20062094@yeah/blog/static/161844416201161974646434/ 1. Create shared memory ...

  4. iPhone实现自定义多选列表

    好久没更新博客了,今天写了一个自定义的多选列表,可以跟爱学习的各位进行分享,首先我们先来看一下效果图: 一般大家都是用UITableView自己的编辑模式来实现CheckBox的,这里我们用自定义Ce ...

  5. PLSQL 创建自定义函数注意事项

    2017-6-8周四,今天遇到的需求是,从数据库中查找出某张表的某些数据,并将这些数据做简单的加减运算再得到结果集,没有思路,后来问辉哥,给我的建议是给这些运算封装成一个SQL函数,select选择字 ...

  6. subsets(子集)

    Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solut ...

  7. HashMap 实现原理

    深入Java集合学习系列:HashMap的实现原理   参考文献 引用文献:深入Java集合学习系列:HashMap的实现原理,大部分参考这篇博客,只对其中进行稍微修改 自己曾经写过的:Hashmap ...

  8. SQLServer2PostgreSQL迁移过程中的几个问题

    1.PostgreSQL 跨平台迁移工具Migration Toolkit的使用指南:http://www.enterprisedb.com/docs/en/8.4/mtkguide/Table%20 ...

  9. Microsoft Visual C++ Compiler for Python 2.7真正下载地址

    真正下载地址: http://origin.www.ms.akadns.NET/en-us/download/details.aspx?id=44266 那个微软地址好像不可用.

  10. Django signals机制的几个简单问题

    1.Django signals机制不是异步执行,是同步执行,所以需要异步执行的耗时任务不能用这个. 2.异步耗时任务不用这个,那些用signals?主要是解耦那些多次重复场合被调用的函数.直接用事件 ...