设计模式一组合模式
一、什么是组合模式?
组合模式(Composite Pattern)是一种结构型设计模式,它允许我们将对象组合成树形结构以表示“部分-整体”的层次结构。通过使用组合模式,我们可以以一致的方式处理单个对象和对象组合,使客户端代码能够透明地操作它们,而不必关心是在处理单个组件还是组合的结构
二、结构组成
组件(Component):定义组合模式中所有对象共有的方法和属性。
叶子节点(Leaf):叶子节点对象,也是组合中没有子节点的对象。
组合节点(Composite):表示组合中的容器对象,该对象包含其他子节点。
三、应用场景
- 文件系统:比如C盘、D盘下面有很多文件夹,文件夹里面又有很多文件或文件夹。
- 二叉树结构。
四、实现
组件(Component):首先,我们定义一个基础接口 FileComponent,它是所有文件系统组件的基础,无论是文件还是文件夹都需要实现这个接口。
import java.util.ArrayList;
import java.util.List;
interface FileComponent {
void printPath(String prefix);
}
然后,我们定义两个类:Folder(组合节点) 和 File(叶子节点)。Folder 类是一个组合节点,它可以包含其他 FileComponent 对象;File 类是一个叶子节点,它代表一个单一的文件。
叶子节点:
class File implements FileComponent {
private String name;
public File(String name) {
this.name = name;
}
@Override
public void printPath(String prefix) {
System.out.println(prefix + "/" + this.name);
}
}
组合节点:
class Folder implements FileComponent {
private String name;
private List<FileComponent> children = new ArrayList<>();
public Folder(String name) {
this.name = name;
}
public void add(FileComponent component) {
children.add(component);
}
public void remove(FileComponent component) {
children.remove(component);
}
@Override
public void printPath(String prefix) {
// 先打印自己本身
System.out.println(prefix + "/" + this.name);
// 再递归打印孩子
for (FileComponent child : children) {
child.printPath(prefix + "/" + this.name);
}
}
}
最后创建测试类。
public class FileSystemTree {
public static void main(String[] args) {
FileComponent root = new Folder("root");
FileComponent file1 = new File("file1.txt");
FileComponent subFolder = new Folder("subfolder");
FileComponent file2 = new File("file2.txt");
// Add components to the folder structure
root.add(file1);
root.add(subFolder);
subFolder.add(file2);
// Print the path of each component in the tree
root.printPath("");
}
}
// 打印结果
/root
/root/subfolder
/root/subfolder/file2.txt
/root/file1.txt
分析
在这个例子中,FileComponent 接口定义了一个方法 printPath,该方法打印出当前文件或文件夹的路径。Folder 类实现了添加和移除子项的功能,并且递归地打印出所有子文件和子文件夹的路径。File 类简单地打印自己的路径。
五、优缺点分析
优点:
- 统一接口:组合模式提供了一致的接口来处理单个对象和组合对象。这意味着客户端代码可以使用相同的接口来操作组件,而不需要知道具体处理的是单个对象还是复合对象。这简化了客户端代码的设计。
- 易于扩展:使用组合模式可以很容易地扩展新的组件类型。只要新组件遵守相同的接口,就可以无缝地集成到现有的结构中。
- 代码复用:组合模式使得代码可以在单个对象和组合对象之间复用,因为它们都实现了相同的接口。
- 灵活的层次结构:组合模式非常适合用来表示具有层次关系的对象结构。例如,文件系统、组织结构图等,都可以利用组合模式来表示。
- 支持递归操作:由于组合模式中的对象是以树形结构组织的,所以它天然支持递归的操作,比如遍历所有的子节点。
- 简化高层模块:高层模块只需要关心Component对象,而不需要关心它到底是Composite还是Leaf,这使得高层模块更加简洁。
缺点:
能引入不必要的复杂性(特别是在对象层次比较简单的情况下)。以及可能消耗更多的内存