如何理解组合设计模式
当我们在某个文件夹下搜索某个文件的时候,通常我们希望搜索的结果包含组合对象的所有子孙对象;开家族会议的时候,开会的命令会被传达到家族中的每一个成员;领导希望我们 996 的时候,只要跟部门领导说一声,部门领导就会通知所有的员工来修福报,无论你是下属哪个组织的,都跑不掉…?
在类似的场景中,有以下特点:
1.结构呈整体-部分的树形关系,整体部分一般称为组合对象,组合对象下还可以有组合对象和叶对象;
2.组合对象和叶对象有一致的接口和数据结构,以保证操作一致;
3.请求从树的最顶端往下传递,如果当前处理请求的对象是叶对象,叶对象自身会对请求作出相应的处理;如果当前处理的是组合对象,则遍历其下的子节点(叶对象),将请求继续传递给这些子节点;
组合模式:
tips:
聚合(aggregation)是关联关系的特例,是强的关联关系,聚合是整个与个体的关系,即has-a关系,此时整体和部分是可以分离的,他们具有各自的生命周期,部分可以属于多个对象,也可以被多个对象共享;比如计算机和CPU,公司与员工的关系;在代码层面聚合与关联是一致的,只能从语义上来区分。
接下来用ts代码实现组合模式
abstract class Component {
protected name : string;
constructor(name : string) {
this.name = name;
}
public abstract doOperation() : void;
public add(component : Component) : void {
}
public remove(component : Component) : void {
}
public getChildren() : Array<Component> {
return [];
}
}
class Composite extends Component {
// 构件容器
private componentList : any;
constructor(name : string) {
super(name);
this.componentList = [];
}
public doOperation() : void {
console.log(`这是容器${
this.name},处理一些逻辑业务!`);
}
public add(component : Component) : void {
this.componentList.push(component);
}
public remove(component : Component) : void {
const componentIndex = this.componentList.findIndex((value : Component, index : Number) => {
return value == component;
});
this.componentList.splice(componentIndex, 1);
}
public getChildren() : Array<Component> {
return this.componentList;
}
}
class Leaf extends Component {
constructor(name : string) {
super(name);
}
public doOperation() : void {
console.log(`这是叶子节点${
this.name},处理一些逻辑业务!`);
}
}
function main() {
const root : Component = new Composite('root-Composite');
const node1 : Component = new Leaf('1-Leaf');
const node2 : Component = new Composite('2-Composite');
const node3 : Component = new Leaf('3-Leaf');
root.add(node1);
root.add(node2);
root.add(node3);
const node2_1 : Component = new Leaf("2_1-Leaf");
node2.add(node2_1);
const children1 = root.getChildren();
console.log(children1);
root.remove(node3);
root.add(node2);
const children2 = root.getChildren();
console.log(children2);
const children3 = node2.getChildren();
console.log(children3);
}
main();
================================================
================================================
================================================
================================================
================================================
组合模式的优点:
由于组合对象和叶对象具有同样的接口,因此调用的是组合对象还是叶对象对使用者来说没有区别,使得使用者面向接口编程;
如果想在组合模式的树中增加一个节点比较容易,在目标组合对象中添加即可,不会影响到其他对象,对扩展友好,符合开闭原则,利于维护;
组合模式的缺点:
增加了系统复杂度,如果树中对象不多,则不一定需要使用;
如果通过组合模式创建了太多的对象,那么这些对象可能会让系统负担不起;