概念
用统一的方式来处理单个对象和一组对象
无论是一个元素,还是一组元素,都用同一套接口、一致的方式去操作
应用场景
当多种对象之间出现了树形嵌套关系,为每一种对象编写一套操作接口过于复杂,使用组合模式可以用同一套接口进行统一操作

基本结构

1)抽象组件(Component):定义了所有组件(包括基本组件和容器组件)必须遵循的接口,比如公共的方法,比如添加、删除、获取子组件等
2)叶子节点(Leaf):代表最基本的、不能再分的对象,比如普通员工。叶子节点实现了抽象组件定义的接口,但不会再包含子节点
3)容器节点(Composite):代表可以包含子组件的对象,比如部门经理。容器节点同样实现了抽象组件接口,同时内部维护着子节点集合,并实现对子节点的添加、删除等操作
代码实现
以 “文件系统管理” 为例
Component
定义统一的文件组件接口:声明操作方法,比如显示信息
public interface FileComponent {
void display(String indent);
}
Leaf
叶子节点类:表示文件
不包含其他子节点,只负责输出自己的名字,是组合结构中最底层的节点
public class FileLeaf implements FileComponent {
private String name;
public FileLeaf(String name) {
this.name = name;
}
public void display(String indent) {
System.out.println(indent + "- 文件:" + name);
}
}
Composite
组合节点类:表示文件夹
可以包含任意数量的子文件或子文件夹,实现递归遍历并展示结构,是组合模式的核心
public class FolderComposite implements FileComponent {
private String name;
private List<FileComponent> children = new ArrayList<>();
public FolderComposite(String name) {
this.name = name;
}
public void add(FileComponent component) {
children.add(component);
}
public void remove(FileComponent component) {
children.remove(component);
}
public void display(String indent) {
System.out.println(indent + "+ 文件夹:" + name);
for (FileComponent child : children) {
child.display(indent + " ");
}
}
}
客户端调用
构建并展示一个文件树结构
客户端不需要关心节点到底是文件还是文件夹,只调用display()方法即可,组合模式让“整体”和“部分”拥有一致的操作方式,实现了对复杂结构的透明访问
public class FileSystemClient {
public static void main(String[] args) {
// 创建文件
FileLeaf file1 = new FileLeaf("readme.txt");
FileLeaf file2 = new FileLeaf("logo.png");
FileLeaf file3 = new FileLeaf("data.csv");
// 创建文件夹
FolderComposite root = new FolderComposite("根目录");
FolderComposite docs = new FolderComposite("文档");
FolderComposite images = new FolderComposite("图片");
// 构建层级关系
docs.add(file1);
images.add(file2);
root.add(docs);
root.add(images);
root.add(file3);
// 显示结构
root.display("");
}
}
+ 文件夹:根目录
+ 文件夹:文档
- 文件:readme.txt
+ 文件夹:图片
- 文件:logo.png
- 文件:data.csv
优缺点
优点
1)统一性:统一使用相同的接口进行操作
2)扩展性:通过递归方式,容易为树形结构添加新的操作或新类型的对象,无需修改已有代码
缺点
1)过度泛化:叶子节点和复合节点使用统一接口,不易区分
