组合模式
组合模式是一种结构型设计模式,它允许你将对象组合成树形结构来表示"部分-整体"的层次结构,使得客户端可以统一处理单个对象和组合对象。
1. 模式结构
角色说明
- Component(抽象组件) 定义叶子和容器的公共接口
- Leaf(叶子节点) 表示树中的叶子节点(没有子节点)
- Composite(容器节点) 存储子组件,实现与子组件相关的操作
2. 关键特点
- 递归组合:容器可以包含其他容器,形成树形结构
- 透明性:叶子节点和容器节点对客户端表现一致
- 统一操作:可以统一处理所有节点,无需区分类型
3. 使用示例:文件系统
// 抽象组件
public abstract class FileSystemComponent {
protected String name;
public FileSystemComponent(String name) {
this.name = name;
}
public abstract void display(int depth);
public abstract void add(FileSystemComponent component);
public abstract void remove(FileSystemComponent component);
}
// 叶子节点(文件)
public class File extends FileSystemComponent {
public File(String name) {
super(name);
}
@Override
public void display(int depth) {
System.out.println("-".repeat(depth) + name);
}
@Override
public void add(FileSystemComponent component) {
throw new UnsupportedOperationException("文件不能添加子节点");
}
@Override
public void remove(FileSystemComponent component) {
throw new UnsupportedOperationException("文件没有子节点");
}
}
// 容器节点(文件夹)
public class Directory extends FileSystemComponent {
private List<FileSystemComponent> children = new ArrayList<>();
public Directory(String name) {
super(name);
}
@Override
public void display(int depth) {
System.out.println("-".repeat(depth) + "[目录] " + name);
for (FileSystemComponent child : children) {
child.display(depth + 2);
}
}
@Override
public void add(FileSystemComponent component) {
children.add(component);
}
@Override
public void remove(FileSystemComponent component) {
children.remove(component);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
Directory root = new Directory("根目录");
Directory docDir = new Directory("文档");
docDir.add(new File("简历.doc"));
docDir.add(new File("报告.pdf"));
Directory imgDir = new Directory("图片");
imgDir.add(new File("照片1.jpg"));
imgDir.add(new File("照片2.jpg"));
root.add(docDir);
root.add(imgDir);
root.add(new File("README.txt"));
root.display(1);
}
}
4. 使用示例:组织结构管理
// 员工和组织结构示例
public class Department extends OrganizationComponent {
public Department(String name) {
super(name);
}
public void print() {
System.out.println("部门: " + name);
super.print();
}
}
public class Employee extends OrganizationComponent {
public Employee(String name, String position) {
super(name);
this.position = position;
}
public void print() {
System.out.println("员工: " + name + " (" + position + ")");
}
}
5. 优缺点
优点:
- 简化客户端代码:统一处理简单和复杂元素
- 易于扩展:新增组件类型不影响现有结构
- 灵活结构:可以动态构建复杂树形结构
缺点:
- 设计抽象较难:过度一般化可能使系统难以理解
- 类型检查问题:可能需要运行时类型检查
- 违反单一职责:组合类需要同时包含管理和业务逻辑