?组合模式是在处理树形结构时而经常使用的设计模式,树形结构一般是由很多节点对象组合而成的一个整体。我们在开发中经常会碰到这样的结构,比如二叉树、多叉树等,映射到真实生活场景中的书的目录结构,部门的层级结构或者是电脑中的文件目录结构等。
?组合模式 是针对树形结构而发展出来的一种设计模式,树形结构是由节点对象组合而成的对象,呈现“个体-整体”的结构,这种模式可以使客户端在操作树形结构的整体或者个体节点对象时,能做出统一的响应,这种整体和个体的概念对客户端来说也是不可见的。
?组合模式 可以很好的做到,复杂树形对象的层次结构与客户端解耦的目的,是一种结构性的设计模式。
?在组合模式中,通常存在三个角色:
?下面,我们通过一个电脑中文件目录树形结构的例子,来写一个组合模式的Demo案例,具体代码如下:
// 抽象的构件
public abstract class AbstractNode {
// 节点名称
protected String name;
// 构造的文件名称
AbstractNode(String name) {
this.name = name;
}
// 添加节点的方法
protected abstract void add(AbstractNode abstractNode);
// 展示节点的方法
protected void show(int lines) {
StringBuilder sb = new StringBuilder("|");
for (int i = 0; i < lines; i++) {
sb.append("—— ");
}
sb.append(name);
System.out.println(sb);
}
}
// 叶子节点 - 文件
public class File extends AbstractNode {
// 构造函数
File(String name) {
super(name);
}
@Override
protected void add(AbstractNode abstractNode) {
// 可以通过抛出异常表示子节点不支持的方法
throw new RuntimeException("叶子构件不支持添加新的节点");
}
@Override
protected void show(int lines) {
// 调用父类的方法
super.show(lines);
}
}
// 容器节点 - 文件夹
public class Folder extends AbstractNode{
// 文件夹下面的子节点(包含容器节点和叶子节点)
private List<AbstractNode> list;
// 构造函数默认赋值
public Folder(String name) {
super(name);
this.list = new ArrayList<>();
}
@Override
protected void add(AbstractNode abstractNode) {
list.add(abstractNode);
}
@Override
protected void show(int lines) {
// 先展示名称
super.show(lines);
// 节点展示 + 1
lines ++;
// 子节点的展示
for (AbstractNode node : list) {
node.show(lines);
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 定义文件夹
AbstractNode folder = new Folder("D盘");
folder.add(new File("日记.txt"));
folder.add(new File("人民的名义.mp4"));
// 添加子文件夹
AbstractNode sonFolder1 = new Folder("音乐");
sonFolder1.add(new File("周杰伦.mp3"));
sonFolder1.add(new File("以父之名.mp3"));
AbstractNode music = new Folder("张杰");
music.add(new File("年轻的战场.mp3"));
sonFolder1.add(music);
AbstractNode sonFolder2 = new Folder("图片");
sonFolder2.add(new File("快看这是美景图.jpeg"));
folder.add(sonFolder1);
folder.add(sonFolder2);
// 文件展示
folder.show(0);
}
}
?执行的结果如下展示:
?根据上面这个代码demo,我们来画一下对应的UML类图吧。
?根据抽象构件中定义的方法,可以分为透明组合模式和安全组合模式两种
?我们来总结一下,组合模式的主要优点: