Skip to content

组合模式(Composite Pattern)


1. 官方定义

"Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly."
—— 《Design Patterns: Elements of Reusable Object-Oriented Software》(GoF, 1994)

核心:将对象组合成树形结构以表示“部分-整体”层次结构,使客户端对单个对象和组合对象的使用具有一致性。

ViewGroup 是 View 的子类,并且 ViewGroup 是一个 View 的容器,也就是说 ViewGroup 可以包含若干个的 ViewGroup 或者 View。 文件夹包含若干个文件夹和文件,也适合组合模式。

2. 模式解释

核心思想

  • 统一接口:叶子节点(单个对象)和容器节点(组合对象)实现相同接口(如 Component)。
  • 递归结构:容器节点可嵌套其他容器或叶子节点(如文件夹包含文件和子文件夹)。
  • 透明性:客户端无需区分处理单个对象或组合对象(统一调用 operation())。

典型结构

plaintext
          |<<Component>>|
          FileSystemItem

              | implements
      ┌───────┴───────┐
      |               |
    File           Folder

                       | contains → FileSystemItem

优点

  • 简化客户端代码:统一处理简单和复杂元素(如递归计算文件夹总大小)。
  • 高扩展性:新增元素类型不影响现有结构(如添加 SymLink 符号链接)。
  • 自然建模:直接映射真实世界的树形结构(如组织架构、XML DOM)。

缺点

  • 接口过度泛化:叶子节点被迫实现无意义的方法(如 File 实现 addChild())。
  • 性能损耗:遍历深层嵌套结构可能影响性能(需结合缓存优化)。

3. 解决的问题

经典场景

  1. 文件系统管理
    • 统一处理文件和文件夹(递归删除、大小统计)。
  2. UI 组件树
    • GUI 中的容器(Panel)和控件(Button)统一渲染。
  3. 菜单系统
    • 支持多级嵌套菜单(主菜单 → 子菜单 → 菜单项)。

4. 实现注意事项

关键实现点

  1. 接口设计
    • 透明式:在 Component 接口定义 add/remove 方法(叶子节点抛出异常)。
    • 安全式:仅在容器接口(如 Folder)定义 add/remove 方法(推荐方式)。
  2. 遍历算法
    • 深度优先(DFS)或广度优先(BFS)遍历树形结构。
  3. 空对象处理
    • 叶子节点对容器操作返回默认值(如 File.getSize() 直接返回文件大小)。

代码示例(安全式实现)

java
// 抽象组件(不包含管理方法)
interface FileSystemItem {
    String getName();
    long getSize();
}

// 叶子节点
class File implements FileSystemItem {
    private String name;
    private long size;
    
    public long getSize() { return size; }
}

// 容器节点
class Folder implements FileSystemItem {
    private List<FileSystemItem> children = new ArrayList<>();
    
    public void addItem(FileSystemItem item) { children.add(item); }
    public long getSize() {
        return children.stream().mapToLong(FileSystemItem::getSize).sum();
    }
}

5. 实现变体

类型特点适用场景
透明式组合所有节点(包括叶子)实现相同的管理接口(add/remove需要极致的接口统一性
安全式组合仅容器节点实现管理接口(更符合现实逻辑)大多数实际场景(推荐)

6. 相似模式对比

模式核心区别
装饰器模式增强单个对象功能,组合模式处理对象集合
享元模式共享细粒度对象,组合模式管理对象结构
访问者模式分离遍历与操作,常与组合模式配合处理复杂结构

7. 组合使用场景

常见搭配模式

  1. 迭代器模式
    • 场景:为组合结构提供统一的遍历接口(如深度优先迭代器)。
  2. 访问者模式
    • 场景:在复杂树形结构上执行多种操作(如文件系统病毒扫描+统计)。
  3. 责任链模式
    • 场景:沿树形结构传递请求(如审批流程沿组织架构树传递)。

总结
组合模式是树形数据建模的标准方案,其核心价值在于通过一致性接口隐藏结构复杂性。安全式实现更符合现实逻辑,而透明式实现追求极致统一。在涉及递归操作的场景(如价格汇总、权限检查)中,组合模式能显著简化代码结构,但需注意避免过度泛化接口。