组合
更新: 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);
}
}
优缺点
优点:
- 简化客户端代码(统一处理简单和复杂元素)
- 更容易添加新类型的组件
- 灵活构建复杂对象结构
- 符合开闭原则(新增组件不影响现有结构)
缺点:
- 限制类型检查(所有组件实现相同接口)
- 可能使设计过度一般化
- 叶子节点实现不需要的方法可能违反接口隔离原则
应用场景
- 表示部分 - 整体层次结构(文件系统、组织架构)
- 需要统一处理组合和单个对象
- 菜单/工具栏等 UI 组件系统
- XML/JSON文档处理
- 表达式解析树(算术表达式、SQL 解析)
与其他模式的关系
- 与装饰器模式:装饰器可视为只有一个组件的组合
- 与迭代器模式:组合常与迭代器配合遍历结构
- 与访问者模式:访问者便于对组合结构执行操作
- 与享元模式:享元可共享叶子节点减少内存
- 与责任链模式:组合结构可实现责任链传递
JDK 中的组合模式
- AWT/Swing组件体系(Component/Container)
- Java 集合框架中的
Map
和List
接口 - JUnit 测试框架中的
TestSuite
和TestCase
- XML 处理中的 DOM 树结构
注意事项
- 合理设计组件接口(避免叶子节点实现不需要的方法)
- 考虑使用空对象模式处理叶子节点的子组件操作
- 注意组合结构的循环引用问题
- 为复合组件提供高效的子组件管理
- 考虑使用缓存优化复合组件的计算操作