持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天
介绍
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
使用场景
-
您想表示对象的部分-整体层次结构(树形结构)
-
您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
-
部分、整体场景,如树形菜单,文件、文件夹的管理。
应用实践
职责明确
- 一个
抽象类,也是暴露给外界的 api; 单个对象,也就是叶子(Leaf)节点,需要继承抽象类
`复合对象`,也就是`容器组件`(Composite),需要继承`抽象类`,区别于 `叶子节点` 的是,存在一个 `children` 属性,用于保存叶子节点以及其他`容器组件`
实现
组合模式(Composite Pattern):组合多个对象形成树形结构以表示“整体-部分”的结构层次。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性
abstract class Component {
protected name: string;
constructor(name: string) {
this.name = name;
}
// 添加
public abstract add(component: Component): void;
// 获取分支下的所有叶子构件和树枝构件
public abstract display(depth: number): void;
}
class Composite extends Component {
private componentArrayList: Component[] = []
constructor(name: string) {
super(name);
}
public add(component: Component): void {
this.componentArrayList.push(component);
}
public display(depth: number): void {
//创建结构
for (let i = 0; i < depth; i++) {
console.log("------")
}
console.log(this.name);
const {
componentArrayList
} = this;
// 遍历下一级
for (let i = 0, item: Component; item = componentArrayList[i++];) {
item.display(depth + 1);
}
}
}
class Leaf extends Component {
constructor(name: string) {
super(name);
}
public add(component: Component): void {
throw new Error("Unsupported request");
}
public display(depth: number): void {
for (let i = 0; i < depth; i++) {
console.log('-');
}
console.log(this.name);
}
}
const compositeOne = new Composite("tree");
const leafOne = new Leaf("node-01");
compositeOne.add(leafOne);
compositeOne.add(new Leaf("node-02"));
compositeOne.add(new Leaf("node-03"));
compositeOne.display(2);
汇总
组合模式中包含一个容器,然而这个容器是由多个包括容器在内的子容器所构成的,组合模式与其子类都拥有相同的方法。但是,组合模式本身并不完成其中具体的细节的一些工作,而是把这些请求递归的传给自己的子类型,最终完成后获取到最终想要的结果。
组合模式如果运用得当,可以大大简化客户的代码。一般来说,组合模式适用于以下这两种情况
1、表示对象的部分——整体层次结构。组合模式可以方便地构造一棵树来表示对象的部分——整体结构。特别是在开发期间不确定这棵树到底存在多少层次的时候。在树的构造最终完成之后,只需要通过请求树的最顶层对象,便能对整棵树做统一的操作。在组合模式中增加和删除树的节点非常方便,并且符合开放——封闭原则
2、客户希望统一对待树中的所有对象。组合模式使客户可以忽略组合对象和子对象的区别,客户在面对这棵树的时候,不用关心当前正在处理的对象是组合对象还是子对象,也就不用写一堆if、else语句来分别处理它们。组合对象和子对象会各自做自己正确的事情,这是组合模式最重要的能力
优点特性
- 组合模式是得客户端代码可以一致的处理单个对象和组合对象,并不需要关心自己处理的是单个对象还是组合对象,大大的简化了客户端的代码。
- 客户端可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端操作;
- 组合模式可以更容易的在组合类中加如新的对象,客户端不会因为加入了新的对象而更改源代码,从何满足开闭原则
- 使用组合模式时可以利用多态和递归的机制更加方便的使用复杂树构建
缺点弊端
- 客户端需要花更多的时间理清类与类之间的层次关系,增大了客户端的复杂程度
- 不容易限制容器中的组成部分
- 不太能够用继承的方式增加构件的新功能
- 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。