Java组合模式
组合模式将对象组合成树形结构,统一处理单个对象和组合对象。
模式定义
意图:将对象组合成树形结构,让客户端统一处理单个和组合对象。
适用场景
- 树形结构数据
- 需要统一处理节点和容器
- 文件系统、组织结构、菜单
模式结构
抽象组件
Java
public abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
// 添加子节点
public void add(Component component) {
throw new UnsupportedOperationException();
}
// 移除子节点
public void remove(Component component) {
throw new UnsupportedOperationException();
}
// 获取子节点
public Component getChild(int index) {
throw new UnsupportedOperationException();
}
// 显示
public abstract void display(int depth);
}
叶子节点
Java
public class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void display(int depth) {
System.out.println("-".repeat(depth) + name);
}
}
组合节点
Java
public class Composite extends Component {
private List<Component> children = new ArrayList<>();
public Composite(String name) {
super(name);
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public Component getChild(int index) {
return children.get(index);
}
@Override
public void display(int depth) {
System.out.println("-".repeat(depth) + name);
for (Component child : children) {
child.display(depth + 2);
}
}
}
使用示例
Java
Composite root = new Composite("root");
root.add(new Leaf("Leaf A"));
root.add(new Leaf("Leaf B"));
Composite branch = new Composite("Branch X");
branch.add(new Leaf("Leaf XA"));
branch.add(new Leaf("Leaf XB"));
root.add(branch);
root.display(1);
// 输出:
// -root
// ---Leaf A
// ---Leaf B
// ---Branch X
// -----Leaf XA
// -----Leaf XB
文件系统示例
Java
public abstract class FileNode {
protected String name;
public FileNode(String name) {
this.name = name;
}
public abstract void show();
public abstract int getSize();
}
// 文件(叶子)
public class File extends FileNode {
private int size;
public File(String name, int size) {
super(name);
this.size = size;
}
@Override
public void show() {
System.out.println("文件: " + name + " (" + size + "KB)");
}
@Override
public int getSize() {
return size;
}
}
// 目录(组合)
public class Directory extends FileNode {
private List<FileNode> children = new ArrayList<>();
public Directory(String name) {
super(name);
}
public void add(FileNode node) {
children.add(node);
}
public void remove(FileNode node) {
children.remove(node);
}
@Override
public void show() {
System.out.println("目录: " + name);
for (FileNode node : children) {
node.show();
}
}
@Override
public int getSize() {
int total = 0;
for (FileNode node : children) {
total += node.getSize();
}
return total;
}
}
// 使用
Directory root = new Directory("root");
root.add(new File("file1.txt", 10));
root.add(new File("file2.txt", 20));
Directory docs = new Directory("docs");
docs.add(new File("readme.md", 5));
docs.add(new File("guide.md", 15));
root.add(docs);
root.show();
System.out.println("总大小: " + root.getSize() + "KB");
透明式 vs 安全式
| 方式 | 特点 | add/remove位置 |
|---|---|---|
| 透明式 | 统一接口 | Component(叶子抛异常) |
| 安全式 | 分离接口 | Composite(叶子无此方法) |
组合模式优点
- 统一处理单个对象和组合对象
- 递归结构自然表达
- 新增组件类型容易
- 简化客户端代码
适用场景
- 文件系统(文件/目录)
- 组织结构(员工/部门)
- 菜单系统(菜单项/菜单组)
- 图形界面(控件/容器)
注意事项
透明式可能导致叶子节点调用不支持方法
安全式需要客户端区分叶子与组合
递归调用注意深度和性能
组合模式天然支持树形遍历
要点总结
- 组合模式构建树形结构,统一处理节点
- Component定义统一接口,Leaf是叶子,Composite是组合
- 透明式将add/remove放在Component,安全式放在Composite
- 文件系统、组织结构是典型应用
- 递归遍历是组合模式的核心操作
📝 发现内容有误?点击此处直接编辑