Composite(组合)模式(对象结构型模式)
将对象组合成树形结构以表示"部分-整体"的层次结构. Composite使得用户对单个对象和组合对象的使用具有一致性.
1. 你想表示对象的部分-整体层次结构.
2. 你希望用户忽略组合对象与单个对象的不同, 用户将统一地使用组合结构中的所有对象.
Component
—为组合中的对象声明接口.
—在适当的情况下, 实现所有类共有接口的缺省行为.
—声明一个接口用于访问和管理Component的子组件(这里的GetChild(int)).
—(可选)在递归结构中定义一个接口, 用于访问一个父部件, 并在合适的情况下实现它.
Leaf
—在组合中表示叶节点对象, 叶节点没有子节点.
—在组合中定义原子对象的行为.
Composite
—定义有子部件的那些部件的行为.
—存储子部件。
—在Component接口中实现与子部件有关的操作.
Client
—通过Component接口操纵组合部件的对象. 对于Client来说操作组合部件与树叶部件是没有区别的.
1. 定义了包含基本对象和组合对象的类层次结构 基本对象可以被组合成更复杂的组合对象, 而这个组合对象又可以被组合, 这样不断的递归下去. 客户代码中, 任何用到基本对象的地方都可以使用组合对象.
2. 简化客户代码 客户可以一致地使用组合结构和单个对象。通常用户不知道(也不关心)处理的是一个叶节点还是一个组合组件。这就简化了客户代码. 但是如果你的需求中需要区分时, 你需要使用一定的方法去区分是一个叶组件还是组合组件.
3. 使得更容易增加新类型的组件新定义的Composite或Composite子类自动地与已有的结构和客户代码一起工作,客户程序不需因新的Component类而改变(例如你可以增加一个组合组件, 这个组合组件是由其他的组合组件组成)
4. 使你的设计变得更加一般化, 容易增加新组件也会产生一些问题, 那就是很难限制组合中的组件. 有时你希望一个组合只能有某些特定的组件. 使用Composite时, 你不能依赖类型系统施加这些约束, 而必须在运行时刻进行检查.
5. Component中的接口是Leaf类接口加上Composite的接口. 这有时可能会与类层次结构设计原则相冲突, 该原则规定: 一个类只能定义那些对它的子类有意义的操作. 有许多Component所支持的操作对Leaf类似乎没有什么意义, 那么可以在Component对这些接口进行缺省操作.
6. 组合组件需要定制一定的策略来管理其子组件. 看你的需求.
7. 这里的子组件不知道其父组件.
例如 一个矢量图系统, 有点, 圆形, 直线(线段), 矩形, 圆弧, 多边形, 不规则图形组成.
很明显 点, 可以作为Leaf
直线: 两个点
圆形: 点 + 半径
圆弧: 圆心 + 始末点 + 方向
矩形: 两个对角点.
多边形:直线(或者点)(看你的需求, 你可以使用一个直线的列表或者使用点的列表来存储多边形).
不规则图形: 直线 + 圆弧
当你需要绘制这些图形的时候就可以使用Composite模式.
这里只使用Composite模式可能不一定能满足需求, 例如Component的Draw函数, 有时为了提套绘图效率, 我们可能不是简单的调用Draw函数, 而是需要判断一下对象的类型来做对应的优化等. Component的子组件不知道它的父组件.
1. 通常部件-父部件连接用于Responsibility of Chain模式.
2. Decorator模式经常与Composite模式一起使用. 当装饰和组合一起使用时,它们通常有一个公共的父类. 因此装饰必须支持具有Add、Remove和GetChild操作的Component接口.
3. Flyweight让你共享组件, 但不再能引用他们的父部件.
4. Itertor可用来遍历Composite.
5. Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化.