描述
- 把一组相似的对象,提取到一个单一抽象对象(通过树形结构组合)。
- 比如文件和文件夹。用户希望的是可以一致操作(都认为是菜单文件)。
角色
- 抽象根节点:各个层次共有属性和行为。比如文件夹,文件都可以增删等。
- 树枝节点:可以存储子节点的节点。比如文件夹。
- 叶子节点:最底层的节点,没有子节点了。比如文件。
分类
- 透明组合模式:标准模式,在抽象根节点声明了所有用于管理对象的方法。某些方法可能会报错(如例子中的 add,remove方法)。
- 安全组合模式:在抽象根节点没有声明任何用于管理对象的方法。不够透明,无法抽象编程,需要区分管理树枝节点和叶子节点。
实现(透明组合模式)
- 把相似的都提取到抽象(菜单文件),(文件和文件夹)实现或继承抽象。可以统一操作抽象。
public class Test {
public static void main(String[] args) {
FileSystem fileSystem = new Folder("一级文件系统", 1);
fileSystem.add(new File("a文件", 2));
Folder folder = new Folder("二级目录", 2);
folder.add(new Folder("三级目录", 3));
folder.add(new File("b文件", 3));
folder.add(new File("c文件", 3));
fileSystem.add(folder);
fileSystem.add(new Folder("C目录", 2));
fileSystem.print();
}
}
abstract class FileSystem {
protected String name;
protected Integer level;
public void add(FileSystem fileSystem) {
throw new RuntimeException("不可增加子节点");
}
public void delete(FileSystem fileSystem) {
throw new RuntimeException("不可删除子节点");
}
public void getChildren() {
throw new RuntimeException("无字节点可以获取");
}
public abstract void print();
}
class Folder extends FileSystem {
private final List<FileSystem> fileSystemList = new ArrayList<>();
Folder(String name, Integer level) {
super.name = name;
super.level = level;
}
@Override
public void add(FileSystem fileSystem) {
fileSystemList.add(fileSystem);
}
@Override
public void delete(FileSystem fileSystem) {
fileSystemList.remove(fileSystem);
}
@Override
public void getChildren() {
System.out.println(Arrays.toString(fileSystemList.toArray()));
}
@Override
public void print() {
StringBuilder space = new StringBuilder();
for (int i = 0; i < level; i++) {
space.append("\t");
}
space.append(name);
System.out.println(space);
fileSystemList.forEach(FileSystem::print);
}
}
class File extends FileSystem {
File(String name, Integer level) {
super.name = name;
super.level = level;
}
@Override
public void print() {
StringBuilder space = new StringBuilder();
for (int i = 0; i < level; i++) {
space.append("\t");
}
space.append(name);
System.out.println(space);
}
}
优点
- 组合模式可以清晰的表达各个层级的节点,忽略层次差异。
- 客户端可以一致操作抽象节点
- 新增树枝节点或根节点,不需要修改原有结构,符合开闭原则。
- 树形结构解决方案。
使用场景