组合模式 (Composite Pattern)
组合模式是一种 结构型设计模式,它将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端可以用统一的方式处理单个对象和组合对象。
原理
- 核心思想:
- 将对象的“部分”与“整体”组织成树形结构,以统一的方式操作单个对象和组合对象。
- 客户端无需关心对象是简单的还是复杂的,它们都遵循相同的接口。
- 适用场景:
- 表示对象的 部分-整体 层次结构。
- 希望客户端对单个对象和组合对象进行一致操作。
- 参与角色:
- Component(抽象构件):为组合中的对象声明接口。
- Leaf(叶子节点):定义组合中的叶子对象。
- Composite(容器构件):定义有子部件的对象,存储子部件并实现
Component
接口。
优点
- 一致性操作:客户端代码可以一致地操作简单对象和组合对象,无需关心具体类型。
- 灵活扩展:可以动态地增加和删除组合中的节点。
- 树形结构:非常适合用于表示复杂的层次结构。
缺点
- 复杂性增加:由于需要支持递归组合,代码可能变得复杂。
- 不易限制类型:在某些场景中,可能希望对子节点类型施加限制,但组合模式的设计使其较难实现。
示例代码
场景描述
设计一个文件系统,包含文件和文件夹,文件夹可以包含文件或子文件夹。用户可以查看文件系统的内容,统一显示文件和文件夹信息。
1. 定义抽象构件
// 抽象构件
public interface FileSystemComponent {
void show(); // 显示组件信息
}
2. 创建叶子节点
// 叶子节点:文件
public class File implements FileSystemComponent {
private String name;
public File(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println("File: " + name);
}
}
3. 创建容器构件
// 容器节点:文件夹
import java.util.ArrayList;
import java.util.List;
public class Folder implements FileSystemComponent {
private String name;
private List<FileSystemComponent> children = new ArrayList<>();
public Folder(String name) {
this.name = name;
}
public void add(FileSystemComponent component) {
children.add(component);
}
public void remove(FileSystemComponent component) {
children.remove(component);
}
@Override
public void show() {
System.out.println("Folder: " + name);
for (FileSystemComponent child : children) {
child.show(); // 递归调用子节点的 show 方法
}
}
}
4. 客户端代码
public class CompositePatternExample {
public static void main(String[] args) {
// 创建文件
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
File file3 = new File("file3.txt");
// 创建文件夹
Folder folder1 = new Folder("folder1");
Folder folder2 = new Folder("folder2");
Folder rootFolder = new Folder("root");
// 组合文件和文件夹
folder1.add(file1);
folder1.add(file2);
folder2.add(file3);
rootFolder.add(folder1);
rootFolder.add(folder2);
// 显示文件系统结构
rootFolder.show();
}
}
输出结果
Folder: root
Folder: folder1
File: file1.txt
File: file2.txt
Folder: folder2
File: file3.txt
UML 类图
+-----------------------+
| FileSystemComponent |
+-----------------------+
| + show() |
+-----------------------+
^ ^
| |
+----------------+ +----------------+
| File | | Folder |
+----------------+ +----------------+
| + show() | | + add() |
| | | + remove() |
+----------------+ | + show() |
+----------------+
|
+----------------+
| List<FileSystemComponent> |
+----------------+
使用场景
- 文件系统:文件和文件夹的树形表示。
- 组织结构:公司组织中部门和员工的层次结构。
- UI组件:如窗口、面板、按钮等组件的嵌套组合。
总结
- 组合模式非常适合用于表示复杂的层次结构,并提供了一致的操作接口。
- 它使得客户端代码能够轻松操作简单对象和组合对象,极大地提高了系统的灵活性。
- 然而,在复杂场景中,设计和实现可能会变得困难,需要合理规划对象的组合关系。