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接口,让用户不知道是LeaforComposite类型,使它们看起来是行为一致的 - 声明
Composite管理子部件的操作,包括使用Cache/Buffer提高操作效率,或者管理增删查改。
协作:操作如果是一个叶子节点,则直接执行,否则由组合节点通过循环的形式执行。
效果:
- 定义了包含基本对象和组合对象的类层次结构。
- 简化客户端代码。用户不用担心组合对象和独立对象的操作 API 不一致性。
- 更容易增加新的类型组件。
- 使设计更加一般化。
关联:
Composite 模式经常伴随:Chain of Responsiblity (请求冒泡处理)、Decorator (动态修饰对象的方法)等设计模式一起使用。
当然 Flyweight 用以共享对象元,以及 Iterator 用来遍历 Composite 对象也是合理的。
使用 Visitor 模式来将本应该分布在 Composite 和 Leaf 类中的操作和行为局部化。
