Skip to content

组合

更新: 6/22/2025 字数: 0 字 时长: 0 分钟

定义

组合模式 (Composite Pattern) 将对象组合成树形结构以表示"部分 - 整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。组合模式通过递归组合实现复杂结构的统一操作。

角色

  • 组件 (Component):声明组合中对象的公共接口
  • 叶子 (Leaf):表示组合中的叶子节点(无子节点)
  • 复合组件 (Composite):存储子组件,实现与子组件相关的操作
  • 客户端 (Client):通过 Component 接口操作组合中的对象

实现

文件系统示例

java
// 组件接口
public interface FileSystemComponent {
    void display(int depth);
    long size();
}

// 叶子节点:文件
public class File implements FileSystemComponent {
    private String name;
    private long size;
    
    public File(String name, long size) {
        this.name = name;
        this.size = size;
    }
    
    @Override
    public void display(int depth) {
        System.out.println("-".repeat(depth) + name + " (" + size + " bytes)");
    }
    
    @Override
    public long size() {
        return size;
    }
}

// 复合组件:目录
public class Directory implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> children = new ArrayList<>();
    
    public Directory(String name) {
        this.name = name;
    }
    
    public void addComponent(FileSystemComponent component) {
        children.add(component);
    }
    
    @Override
    public void display(int depth) {
        System.out.println("-".repeat(depth) + "[" + name + "]");
        for (FileSystemComponent child : children) {
            child.display(depth + 2);
        }
    }
    
    @Override
    public long size() {
        long total = 0;
        for (FileSystemComponent child : children) {
            total += child.size();
        }
        return total;
    }
}

组织结构图示例

java
// 抽象组件
public abstract class OrganizationComponent {
    protected String name;
    
    public OrganizationComponent(String name) {
        this.name = name;
    }
    
    public abstract void add(OrganizationComponent component);
    public abstract void remove(OrganizationComponent component);
    public abstract void display(int depth);
}

// 复合组件:部门
public class Department extends OrganizationComponent {
    private List<OrganizationComponent> members = new ArrayList<>();
    
    public Department(String name) {
        super(name);
    }
    
    @Override
    public void add(OrganizationComponent component) {
        members.add(component);
    }
    
    @Override
    public void remove(OrganizationComponent component) {
        members.remove(component);
    }
    
    @Override
    public void display(int depth) {
        System.out.println("-".repeat(depth) + "部门:" + name);
        for (OrganizationComponent member : members) {
            member.display(depth + 2);
        }
    }
}

// 叶子节点:员工
public class Employee extends OrganizationComponent {
    public Employee(String name) {
        super(name);
    }
    
    @Override
    public void add(OrganizationComponent component) {
        throw new UnsupportedOperationException("员工不能添加下属");
    }
    
    @Override
    public void remove(OrganizationComponent component) {
        throw new UnsupportedOperationException("员工不能移除下属");
    }
    
    @Override
    public void display(int depth) {
        System.out.println("-".repeat(depth) + "员工:" + name);
    }
}

优缺点

优点:

  1. 简化客户端代码(统一处理简单和复杂元素)
  2. 更容易添加新类型的组件
  3. 灵活构建复杂对象结构
  4. 符合开闭原则(新增组件不影响现有结构)

缺点:

  1. 限制类型检查(所有组件实现相同接口)
  2. 可能使设计过度一般化
  3. 叶子节点实现不需要的方法可能违反接口隔离原则

应用场景

  1. 表示部分 - 整体层次结构(文件系统、组织架构)
  2. 需要统一处理组合和单个对象
  3. 菜单/工具栏等 UI 组件系统
  4. XML/JSON文档处理
  5. 表达式解析树(算术表达式、SQL 解析)

与其他模式的关系

  • 与装饰器模式:装饰器可视为只有一个组件的组合
  • 与迭代器模式:组合常与迭代器配合遍历结构
  • 与访问者模式:访问者便于对组合结构执行操作
  • 与享元模式:享元可共享叶子节点减少内存
  • 与责任链模式:组合结构可实现责任链传递

JDK 中的组合模式

  1. AWT/Swing组件体系(Component/Container)
  2. Java 集合框架中的MapList接口
  3. JUnit 测试框架中的TestSuiteTestCase
  4. XML 处理中的 DOM 树结构

注意事项

  1. 合理设计组件接口(避免叶子节点实现不需要的方法)
  2. 考虑使用空对象模式处理叶子节点的子组件操作
  3. 注意组合结构的循环引用问题
  4. 为复合组件提供高效的子组件管理
  5. 考虑使用缓存优化复合组件的计算操作

贡献者

The avatar of contributor named as LI SIR LI SIR
The avatar of contributor named as wkwbk wkwbk

页面历史