组合模式是一种结构型设计模式,允许你将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得客户端可以统一对待单个对象和对象的组合。
结构
- 组件接口(Component): 声明了叶子和容器对象的共同接口,客户端通过该接口操作组合结构中的对象。
public interface Component {
void operation();
}
- 叶子类(Leaf): 实现了组件接口,表示组合中的叶子对象,叶子对象没有子节点。
public class Leaf implements Component {
public void operation() {
System.out.println("Leaf operation");
}
}
- 容器类(Composite): 实现了组件接口,表示组合中的容器对象,可以包含子节点(既可以是叶子对象,也可以是其他容器对象)。
import java.util.ArrayList;
import java.util.List;
public class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
public void operation() {
System.out.println("Composite operation");
for (Component component : children) {
component.operation();
}
}
}
优点和缺点
优点:
- 统一接口: 组合模式统一了单个对象和组合对象的接口,使得客户端可以一致地处理它们。
- 灵活性: 客户端可以像处理单个对象一样,处理组合对象,从而使得系统更加灵活。
- 递归结构: 组合模式构建了递归结构,使得客户端可以通过统一的方式遍历所有的叶子对象和容器对象。
缺点:
- 不易限制组件类型: 组合模式将叶子对象和容器对象都看作组件对象,难以限制容器对象只能包含特定类型的子节点。
示例
以下是一个组合模式的示例,表示一个文件系统的目录结构,其中文件和文件夹都是组件,文件夹可以包含其他文件和文件夹。
// 组件接口
public interface Component {
void operation();
}
// 叶子类
public class File implements Component {
private String name;
public File(String name) {
this.name = name;
}
public void operation() {
System.out.println("File: " + name);
}
}
// 容器类
import java.util.ArrayList;
import java.util.List;
public class Folder implements Component {
private String name;
private List<Component> children = new ArrayList<>();
public Folder(String name) {
this.name = name;
}
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
public void operation() {
System.out.println("Folder: " + name);
for (Component component : children) {
component.operation();
}
}
}
// 客户端代码
public class Main {
public static void main(String[] args) {
Component file1 = new File("file1.txt");
Component file2 = new File("file2.txt");
Component folder1 = new Folder("Folder 1");
Component folder2 = new Folder("Folder 2");
folder1.add(file1);
folder1.add(file2);
folder2.add(folder1);
folder2.operation();
}
}
在这个例子中,File 是叶子类,表示文件对象,Folder 是容器类,表示文件夹对象。客户端可以创建文件和文件夹,将文件添加到文件夹中,然后通过统一的接口调用它们的 operation 方法,实现对整个文件系统的操作。