目录
- 7、组合模式
- 7.1 组合模式(Composite)
- 7.2 叉树结构
- 7.3 文件系统
- 7.4 目录树展示
- 7.5 自相似性的涌现
- 7.6 组合模式的各角色定义
- 7.7 组合
7、组合模式
7.1 组合模式(Composite)
- 是针对由多个节点对象(部分)组成的树形结构的对象(整体)而发展出的一种结构型设计模式
- 它能够使客户端在操作整体对象或者其下的每个节点对象时做出统一的响应,保证树形结构对象使用方法的一致性
- 整体和部分,有类似结构
- 测试类结构
7.2 叉树结构
- 某些具有从属关系的事物之间存在着一定的相似性
- 不管从哪个层级,我们都会得到一个固定的结构
- 这种结构类似于经典的“叉树”结构:无论数据元素是“根”“枝”,还是“叶”,甚至是整体的树,都具有类似的结构
- 我们可以用组合模式来表达“部分/整体”的层次结构,提取并抽象其相同的部分,特殊化其不同的部分,以提高系统的可复用性与可扩展性
7.3 文件系统
- 以类似于树结构的文件系统的目录结构为例
- 抽象节点类Node
- 定义一个抽象的“节点”类来模糊“文件夹”与“文件”
- 构造方法中接收并初始化已定义的节点名,否则不允许节点被创建,这也是可以固化下来的逻辑。
- 声明抽象方法,模糊行为并留给子类去实现
package composite;
public abstract class Node {protected String name;public Node(String name) {this.name = name;}protected abstract void add(Node child) throws Exception;
}
- 节点实现类1:文件夹类Folder
- 文件夹类继承了抽象节点类Node
- 文件夹下级可以包含任意多个文件夹或者文件:次级节点列表List
package composite;import java.util.ArrayList;
import java.util.List;
public class Folder extends Node {List<Node> children = new ArrayList<>();public Folder(String name) {super(name);}@Overrideprotected void add(Node child) {children.add(child);}
}
package composite;
public class File extends Node {public File(String name) {super(name);}@Overrideprotected void add(Node child) {System.out.println("文件类型不能添加子节点");}
}
package composite;
public class Client {public static void main(String[] args) throws Exception {Node driveD = new Folder("测试盘");Node doc = new Folder("文档");doc.add(new File("简历.doc"));doc.add(new File("项目介绍.ppt"));driveD.add(doc);Node music = new Folder("音乐");Node jay = new Folder("周杰伦");jay.add(new File("双截棍.mp3"));jay.add(new File("告白气球.mp3"));jay.add(new File("听妈妈的话.mp3"));Node jack = new Folder("张学友");jack.add(new File("吻别.mp3"));jack.add(new File("一千个伤心的理由.mp3"));music.add(jay);music.add(jack);driveD.add(music);}
}
7.4 目录树展示
- 要体现出组合模式的优势还在于如何运用这个树结构
- 分级展示整棵目录树
- 输出节点名称(文件夹名/文件名)之前加上数个空格以表示不同层级
- 修改抽象节点类Node并加入展示方法tree()
protected void tree(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}protected void tree() {this.tree(0);}
- 节点实现类File和Folder重写展示方法,Folder还要展示其子级
@Overridepublic void tree(int space) {super.tree(space);space++;for (Node child : children) {child.tree(space);}}
@Override
public void tree(int space){super.tree(space);
}
- 客户端在任何一级节点上只要调用其展示方法并传入当前目录所需的空格偏移量,就可出现树形列表了
driveD.tree();
- 空格偏移量这个必传参数,可以为抽象节点类添加一个无参的展示方法,默认为0
7.5 自相似性的涌现
- 组合模式将树形结构的特点发挥得淋漓尽致
- 作为最高层级抽象的抽象节点类(接口)泛化了所有节点类,使任何“整体”或“部分”达成统一
- 枝(根)节点与叶节点的多态化实现以及组合关系进一步勾勒出的树形结构
7.6 组合模式的各角色定义
- Component(组件接口):
- 所有复合节点与叶节点的高层抽象,定义出需要对组件操作的接口标准
- 如抽象节点类Node,具体使用接口还是抽象类需根据具体场景而定。
- Composite(复合组件):
- 包含多个子组件对象(可以是复合组件或叶端组件)的复合型组件,并实现组件接口中定义的操作方法。
- 如:“根节点/枝节点”的文件夹类Folder
- Leaf(叶端组件):
- 不包含子组件的终端组件,同样实现组件接口中定义的操作方法。
- 如: “叶节点”的文件类File
- Client(客户端):
- 按所需的层级关系部署相关对象并操作组件接口所定义的接口,即可遍历树结构上的所有组件
7.7 组合
- 类似的结构总是在重复、迭代地显现出某种自似性
- 其部分与整体一致的呈现与“组合模式”如出一辙