组合模式是用于把一组相似的对象组合为一个对象。将对象组合成树形结构以表示“部分-整体”的层次结构。它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。例如windows中的文件夹及时一种组合模式,一个文件夹下可能包含多个文件夹,每个文件夹又有可能包含其他的文件夹。
下面使用代码来演示文件夹的例子。
首先有一个文件夹的类,文件夹的属性先不考虑其他,只有一个名称和一个子文件列表。
public class Folder {
private String name;
private List<Folder> folderList;
public Folder(String name) {
this.name = name;
this.folderList = new ArrayList<>();
}
/**
* 添加子文件夹
* @param folder 子文件夹对象
*/
public void addSubFolder(Folder folder){
folderList.add(folder);
}
public List<Folder> getFolderList() {
return folderList;
}
@Override
public String toString() {
return name;
}
}
初始化6个文件夹,按照一级文件夹中二级文件夹,二级文件夹中是三级文件夹的规则将这6个文件夹组合起来,编写一个打印函数按照层级结构递归打印出文件夹的层次结构。
public class Main {
public static void main(String[] args) {
Folder folder1_1 = new Folder("一级文件夹");
Folder folder2_1 = new Folder("二级文件夹_1");
Folder folder2_2 = new Folder("二级文件夹_2");
Folder folder3_1 = new Folder("三级文件夹_1");
Folder folder3_2 = new Folder("三级文件夹_2");
Folder folder3_3 = new Folder("三级文件夹_3");
folder2_1.addSubFolder(folder3_1);
folder2_1.addSubFolder(folder3_2);
folder2_2.addSubFolder(folder3_3);
folder1_1.addSubFolder(folder2_1);
folder1_1.addSubFolder(folder2_2);
printFolder(folder1_1,-1);
}
private static void printFolder(Folder folder ,int level){
level++;
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println(folder.toString());
for (Folder subFolder: folder.getFolderList()) {
printFolder(subFolder,level);
}
}
}
运行结果如下图所示:
组合模式就是一种树形结构,与数据结构中的多叉树的结构都是一致的,使用中可按照自己的需求对每个节点增加属性,但是大体的结构都是相似的。
组合模式优点:
-
高层节点的调用简单,下层节点都可以从高层节点的关系中找到。
-
使用灵活,可以自由的组织节点之间的关系。
组合模式缺点:
-
在使用组合模式时,节点的声明都是实现类,而不是接口,违反了依赖倒置原则。
-
设计较复杂,使用者需要组织结构关系,当下级节点的子节点引用了上级节点时会出现环状结构,导致递归时无法退出。
-
子节点不容易被限制。