组合模式的使用场景:
1、存在一批组织成某种层次体系的对象
2、希望对这批对象或其中的一部分对象实施一个操作。
组合模式的特点:
1、组合模式中只有两种类型对象:组合对象、叶子对象
2、这两种类型都实现同一批接口
3、一般我们会在组合对象中调用其方法并隐式调用"下级对象"的方法(这里我们一般采用递归的形式去做)
/**
* 组合模式应用的场景和特点:
场景:
1、存在一批组织成某种层次体系的对象那个
2、希望对这批对象或其中的一个部分对象实施一个操作
应用特点:
1、组合模式中只有两种类型对象:组合对象、叶子对象
2、这两种类型都实现同一批接口
3、一般我们会在组合对象中调用其方法并瘾式调用‘下级对象’的方法(这里我们一般采用递归的形势去做)
* 场景模拟:
* -> 公司
* -> 北京分公司
* -> 财务部门
* -> 张1
* -> 张2
* -> 张3
* -> 销售部门
* -> 张4
* -> 张5
* -> 张6
-> 上海分公司
* -> 财务部门
* -> 张7
* -> 张8
* -> 张9
* -> 销售部门
* -> 张10
* -> 张11
* -> 张12
*
*实际的任务具体是落实到人上去实施的 也就是说只有人才具有具体的方法实现
*
*/
//这两个类型必须实现同一个接口
//添加方法和取得方法
var CompositeInterface = new Fan.Interface('CompositeInterface',['addChild','getChild']);
//努力工作和努力睡觉
var LeafInterface = new Fan.Interface('LeafInterface',['hardworking','sleeping']);
//组合对象
var Composite = function(name){
this.name = name;
this.type = 'Composite'; //说明对象的类型,方便判断他是组合对象还是叶子对象
this.children = []; //承装子类的数组
};
Composite.prototype = {
constructor : Composite,
addChild : function(child){
this.children.push(child);
return this;
},
getChild : function(name){
//接受叶子对象类型数组
var elements = [];
//判断对象是否为Leaf类型的
var pushLeaf = function(item){
if(item.type === 'Composite'){
item.children.each(arguments.callee);
}else if(item.type === 'Leaf'){
elements.push(item);
}
};
if(name && this.name !== name){ //根据name传值,指定name下的所有类型leaf对象去执行操作
this.children.each(function(item){
//如果传入的name是二级子节点名称
if(this.name === name && item.type === 'Composite'){
item.children.each(pushLeaf);
}
//如果传递的name是三级节点或者是N级
if(this.name !== name && item.type === 'Composite'){
item.children.each(arguments.callee);
}
//如果传递的name是叶子节点
if(this.name === name && item.type === 'Leaf'){
elements.push(item);
}
})
}else{ //不传name,让整个公司所有类型为Leaf的对象去执行操作
//org.hardworking();没有传值,就遍历公司所有部门
this.children.each(pushLeaf);
}
return elements;
},
hardworking : function(name){
//得到所有的Leaf类型的对象数组
var leafObject = this.getChild(name);
for(var i=0; i<leafObject.length; i++){
leafObject[i].hardworking();
}
},
sleeping : function(name){
var leafObject = this.getChild(name);
for(var i=0; i<leafObject.length; i++){
leafObject[i].sleeping();
}
}
}
//叶子对象
var Leaf = function(name){
this.name = name;
this.type = 'Leaf';
};
Leaf.prototype = {
constructor : Leaf,
//叶子节点方法无法再调用下一级
addChild : function(child){
throw new Error('不能被使用');
},
getChild : function(name){
if(this.name == name){
return this;
}
return name;
},
hardworking : function(name){
console.log(this.name + '努力工作...');
},
sleeping : function(name){
console.log(this.name + '努力睡觉...');
}
}
//测试数据
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');
var dept1 = new Composite('北京开发部门');
dept1.addChild(p1).addChild(p2).addChild(p3);
var dept2 = new Composite('北京销售部门');
dept2.addChild(p4).addChild(p5).addChild(p6);
var dept3 = new Composite('上海开发部门');
dept3.addChild(p7).addChild(p8).addChild(p9);
var dept4 = new Composite('上海销售部门');
dept4.addChild(p10).addChild(p11).addChild(p12);
var org1 = new Composite('北京分公司');
org1.addChild(dept1).addChild(dept2);
var org2 = new Composite('上海分公司');
org2.addChild(dept3).addChild(dept4);
var org = new Composite('深圳总部');
org.addChild(org1).addChild(org2);
org.hardworking('张7');