组合模式是一种结构型设计模式, 允许将对象组合成树形结构表示 “部分-整体” 的层次结构. 组合模式使得客户端对单个对象和组合对象的使用具有一致性
组合模式结构
- 抽象组件: 定义了组合对象和叶子对象的接口, 包括添加, 删除子组件以及其他共享的行为
- 叶子节点: 代表组合中的叶子对象, 它没有子节点, 定义了对象的基本行为
- 组合节点: 定义有子组件的那些对象, 存储子组件, 并实现抽象组件中的相关操作
组合模式实现
假设要实现一个文件系统, 包括文件和目录, 目录包含文件和子目录, 可以用组合模式来实现这个系统
abstract class FileSystemComponent { public void add(FileSystemComponent component) { throw new UnsupportedOperationException(); }
public void remove(FileSystemComponent component) { throw new UnsupportedOperationException(); }
public FileSystemComponent getChild(int index) { throw new UnsupportedOperationException(); }
public abstract void display(String indent); }
class File extends FileSystemComponent { private String name;
public File(String name) { this.name = name; }
@Override public void display(String indent) { System.out.println(indent + "File: " + name); } }
class Directory extends FileSystemComponent { private String name; private List<FileSystemComponent> components = new ArrayList<>();
public Directory(String name) { this.name = name; }
@Override public void add(FileSystemComponent component) { components.add(component); }
@Override public void remove(FileSystemComponent component) { components.remove(component); }
@Override public FileSystemComponent getChild(int index) { return components.get(index); }
@Override public void display(String indent) { System.out.println(indent + "Directory: " + name); for (FileSystemComponent component : components) { component.display(indent + " "); } } }
public class Client { public static void main(String[] args) { FileSystemComponent file1 = new File("File1.txt"); FileSystemComponent file2 = new File("File2.txt"); FileSystemComponent file3 = new File("File3.txt");
FileSystemComponent directory1 = new Directory("Directory1"); FileSystemComponent directory2 = new Directory("Directory2");
directory1.add(file1); directory1.add(file2);
directory2.add(file3); directory2.add(directory1);
directory2.display(""); } }
|
优点:
- 清晰的层次结构. 通过组合模式可以清晰地表示对象的部分-整体层次结构
- 一致的处理方法: 客户端可以一致地使用组合对象和叶子对象, 无需关注它们的具体类型, 有助于提高系统的灵活性
- 简化客户端代码: 客户端可以统一处理组合对象和叶子对象, 减少了处理不同对象类型的复杂性
- 容易拓展: 可以很容易地添加新的组合对象和叶子对象而不会影响现有代码
缺点: