组合模式
组合模式
对象的结构型模式

模式动机
考虑一个文件树遍历场景:

对于树形结构,当容器对象比如文件夹的某个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象(可能还是容器比如子文件夹,也可能是叶子比如文件)并递归调用
由于容器对象和叶子对象在功能上的区别,客户端在使用它们时必须有区别地对待容器和叶子对象,但是我们希望客户端一致的处理它们,而不是添加复杂的条件控制语句。在这种需求下,组合模式应运而生。
组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须进行区分,可以一致地对待容器对象和叶子对象。
应用
组合模式组合多个对象形成树形结构以表示“整体-部分”的结构层次,对叶子对象和组合对象(即容器对象)的使用具有一致性。
组合模式包含如下角色:
- 抽象构件Component
- 叶子构件Leaf
- 容器构件Composite
- 客户类Client
关键是定义一个抽象构件类,使其既可以代表叶子也可以代表容器,从而让客户端可以面向抽象构件类编程,无需区分是叶子还是容器。
同时容器对象和抽象构件类之间还建立了聚合关系,代表容器之下亦有子节点,这个子节点既可以是容器也可以是叶子。(N叉树的结构)
典型抽象构件类代码如下:
public abstract class Component { |
典型叶子构件类代码如下:
public class Leaf extends Component { |
典型的容器构件类代码如下:
public class Composite extends Component { |
实例:文件系统

实例:水果盘
水果盘中有水果,还有些更小的水果盘,现在需要吃水果,对于水果盘,吃就是吃里面的水果/果盘

实例:文件浏览
文件有不同类型,不同类型文件的浏览方式有所不同,比如文本文件和图片文件。文件系统中还有文件夹,对文件夹的浏览就是浏览其中的文件和子文件夹,现在希望客户端一致的操作不同类型文件和文件夹。

优点
- 清楚地定义分层次复杂对象,增加新构件也容易
- 客户端调用简单,可以一致地处理组合对象和单个对象
- 定义了类层次结构,叶子对象和容器对象都可以进一步递归地组合成容器对象,可以形成复杂的树形结构
- 更容易在组合体内加入对象构件,客户端不会因为加入新的构件而修改原来的代码,符合开闭原则
缺点
- 设计更加抽象,如果对象的业务规则很复杂,那其实很难实现组合模式,因为很难把不同的(叶子和容器)复杂对象的处理接口暴露成一模一样的,并且不是所有的方法都和叶子类有关联(比如容器的某个方法是容器特有的与叶子毫无关系)
- 很难对容器中的构建类型进行限制,因为都是抽象构件类
适用场合
- 需要表示对象的整体或部分层次,且在这个整体-部分的层次结构中希望忽略整体与部分的差异,一致地处理它们
- 客户希望忽略不同对象的层次差异,面向抽象构件编程,无需关心对象层次结构的细节
- 对象的结构是动态变化的并且复杂程度不一样,但是客户需要一致地处理它们
示例:XML文件解析
XML文件是典型的层次结构,层次清晰
|

模式扩展
带复杂继承的组合模式

透明组合模式

安全组合模式

(•‿•)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 (๑>ᴗ<๑)!
评论