A structure of simple and composite objects which makes the total object more than just the sum of its parts.
将对象组合成「树形结构」以表示「部分」和「整体」的层次结构。Composite 使得用户对单个对象和组合对象的使用具有「一致性」。
动机:创建较为复杂的数据对象层次结构,比如 DOM Tree。
适用性:
- 表示对象的「部分 - 整体」的层次结构。
- 希望用户忽略组合对象和单个对象的不同,用户统一地使用组合结构中所有的对象。
代码结构:
典型的 MVC 中,View 层就是经典的「Composite」的案例。
declare interface IDrawable {
draw();
}
class Graphic implements IDrawable {
public draw() {};
}
class Line extends Graphic {
public draw() {};
}
class Text extends Graphic {
public draw() {};
}
class Picture extends Graphic {
public draw() {};
}
class CompositeGraphic implements IDrawable {
private _children: Graphic[];
// 使之行为和 Graphc 保持一致
public draw() {
this._children.forEach(c => c.draw());
}
}
class GraphicBook {
public recursivelyParse(elements) {
return new CompositeGraphic(elements);
}
public parse(ele) {
if (Graphic.isLine(ele)) return new Line(ele);
return typeof ele === 'string' ? new Text(ele) : new Picture(ele);
}
public generatePresentationLayer(str) {
const treeData = JSON.parse(str);
return treeData.map(t => t.children ? recursivelyParse(t.children) : parse(t));
}
}
实现思路:
- 考虑「显式地」父组件引用。
- 考虑「共享」组件和
Flyweight
模式的使用。 - 最大化
Composite
接口,让用户不知道是Leaf
orComposite
类型,使它们看起来是行为一致的 - 声明
Composite
管理子部件的操作,包括使用Cache
/Buffer
提高操作效率,或者管理增删查改。
协作:操作如果是一个叶子节点,则直接执行,否则由组合节点通过循环的形式执行。
效果:
- 定义了包含基本对象和组合对象的类层次结构。
- 简化客户端代码。用户不用担心组合对象和独立对象的操作 API 不一致性。
- 更容易增加新的类型组件。
- 使设计更加一般化。
关联:
Composite
模式经常伴随:Chain of Responsiblity
(请求冒泡处理)、Decorator
(动态修饰对象的方法)等设计模式一起使用。
当然 Flyweight
用以共享对象元,以及 Iterator
用来遍历 Composite
对象也是合理的。
使用 Visitor
模式来将本应该分布在 Composite
和 Leaf
类中的操作和行为局部化。