公号:码农充电站pro
主页:https://codeshellme.github.io
本篇来介绍组合模式(Composite Design Pattern)。
1,组合模式
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
如果对象之间呈树形结构,是一种部分与整体的关系,这种情况都比较适合用组合模式。
组合模式构建的树状关系如下所示:
组合模式使得我们构建这种树状关系变得极为简单。aComposite 是组合对象,aLeaf 是个体对象。组合对象中可以嵌套组合对象和个体对象,个体对象中不能再包含其它对象。
因为组合对象中可以再次嵌套组合对象,所以组合模式也是一种递归关系。
组合模式的类图如下:
从类图中可以看到,Component 为所有的对象提供了统一的接口。组合对象中有 add
和 remove
操作,说明组合对象中可以添加和删除组合对象与个体对象。
注意 Leaf 节点中只有 operation 操作,因为 Leaf 节点不能再嵌套其它节点。
组合对象和个体对象中都有 operation
操作,使得我们能够把相同的操作应用在组合对象和个别对象上。
2,组合模式示例
下面举个例子,来看下如何使用组合模式。
我们已经知道,组合模式非常适合表示树形结构,而 Linux 目录结构就是一个树形结构。下面就用组合模式来构建目录结构。
我们知道目录中即可包含目录,也可包含文件。根据组合模式的类图,可设计出下面的 Linux 文件系统类图:
文件系统可以包括文件和目录,目录中可以嵌套目录和文件,而文件中不能再嵌套其它东西。所以,File 类中没有 add
和 remove
方法。
首先创建 FileSystem 抽象类:
@H_403_103@abstract class FileSystem { protected String path; public abstract void printFile(); }
再创建 File 类:
@H_403_103@class File extends FileSystem { public File(String path) { this.path = path; } public void printFile() { System.out.println(path); } }
File 类继承了 FileSystem, 因为 File 类本身就是文件,所以它的 printFile
非常简单。
再创建 Directory 类:
@H_403_103@class Directory extends FileSystem { private List<FileSystem> nodes; // 用于存储节点 public Directory(String path) { this.path = path; this.nodes = new ArrayList<>(); } public void printFile() { System.out.println(path); // 递归输出目录和文件 for (FileSystem node: nodes) { node.printFile(); } } public void addNode(FileSystem node) { nodes.add(node); } public void removeNode(FileSystem node) { nodes.remove(node); } }
注意区分 File 类和 Directory 类的不同。
下面来测试代码,假设我们要构建这样的目录结构:
test/
├── a
├── b
│ ├── 1.txt
│ └── d
│ └── 2.txt
└── c
└── 3.txt
首先创建文件节点和目录节点:
@H_403_103@// 创建文件节点 File txt1 = new File("test/b/1.txt"); File txt2 = new File("test/b/d/2.txt"); File txt3 = new File("test/c/3.txt"); // 创建目录节点 Directory test = new Directory("test/"); Directory a = new Directory("test/a/"); Directory b = new Directory("test/b/"); Directory c = new Directory("test/c/"); Directory d = new Directory("test/b/d/");
构建目录结构:
@H_403_103@// 构造目录结构 test.addNode(a); test.addNode(b); test.addNode(c); b.addNode(txt1); b.addNode(d); c.addNode(txt3); d.addNode(txt2);
输出 test 目录:
@H_403_103@test.printFile();
结果如下:
test/
test/a/
test/b/
test/b/1.txt
test/b/d/
test/b/d/2.txt
test/c/
test/c/3.txt
输出 b 目录:
@H_403_103@b.printFile();
结果如下:
test/b/
test/b/1.txt
test/b/d/
test/b/d/2.txt
@H_403_103@test.removeNode(b); test.printFile();
结果如下:
test/
test/a/
test/c/
test/c/3.txt
通过测试结果可以看到,我们构建的目录结构是没有问题的。
3,总结
组合模式将一组对象组织成树形结构,对象分为个体对象和组合对象,组合对象中可以包含个体对象和组合对象。组合模式会以递归的方式来处理树的节点。
使用组合模式的前提是,对象之间的关系要符合树形结构的特点。组合模式使得处理树形结构的对象关系变得非常简单。
(本节完。)
推荐阅读:
欢迎关注作者公众号,获取更多技术干货。