一、描述
首先,看一个数据结构:
在平时开发过程中,我们的菜单目录、文件夹目录等都有类似如上的实体结构,其中composite代表父级节点,leaf代表叶子节点,composite可以有子节点,但是leaf下没有节点。解析此结构时,循环解析每个节点,当解析到叶子节点时,当前循环结束。这种数据结构就是组合模式的代表结构。
定义:
组合模式将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
角色
(1)Component(抽象构件):为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。定义了管理子构件的方法,如定义了新增构件、删除构件、获取构件的方法等。
(2)Composite(中间构件):提供一个集合包含其他构件或者叶子节点,实现抽象构件方法,管理集合中的节点。
(3)Leaf(叶子节点):实现抽象构件方法,但是其没有子节点。
类图
二、优点
(1)高层模块调用简单。一颗树形结构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,高层模块不必关心自己处理的是单个对象还是整个组合接口。
(2)节点自由添加
三、缺点
(1)使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒转原则
四、使用场景
(1)维护和展示部分-整体关系的场景(树形菜单、文件和文件夹管理)
(2)一个整体中能够独立出部分模块或功能的场景
五、示例
以“电脑硬盘上的文件夹以及文件为例”,文件夹下有文件,文件夹是具体构件,文件是叶子节点。下面是代码:
(1)IFile,定义文件公共方法
public interface IFile {
/**
* 添加文件或者文件夹
*
* @param iFile
*/
void add(IFile iFile);
/**
* 删除文件或者文件夹
*
* @param iFile
*/
void delete(IFile iFile);
/**
* 获取文件或者文件夹
*
* @return
*/
void operation();
/**
* 获取文件信息
*
* @param i
* @return
*/
IFile get(int i);
}
(2)定义中间构件Folder
public class Folder implements IFile {
//存储文件集合
private List<IFile> children = new ArrayList<>();
//文件夹名称
private String name;
public Folder(String name) {
this.name = name;
}
@Override
public void add(IFile iFile) {
children.add(iFile);
}
@Override
public void delete(IFile iFile) {
children.remove(iFile);
}
@Override
public void operation() {
System.out.println(name + "文件夹,其下有:");
for (int i = 0; i < children.size(); i++) {
System.out.print("-");
children.get(i).operation();
}
}
@Override
public IFile get(int i) {
return children.get(i);
}
}
(3)叶子节点File,文件
public class File implements IFile {
private String name;
public File(String name) {
this.name = name;
}
@Override
public void add(IFile iFile) {
System.out.println("叶子节点无法添加文件");
}
@Override
public void delete(IFile iFile) {
System.out.println("叶子节点无法删除文件");
}
@Override
public void operation() {
System.out.println(name + "文件");
}
@Override
public IFile get(int i) {
return this;
}
}
(4)Client,客户端
文件夹结构如下:
d:
-code:
--company:
---projectA:
----classA1
---projectB
----classB1
-me
--myproject:
---excelA.xls
public class Client {
public static void main(String[] args) {
//D盘下有code文件夹,code文件夹下有company和me文件夹,文件夹下是项目,项目下是代码文件
Folder d = new Folder("d盘");
Folder code = new Folder("code");
Folder company = new Folder("company");
Folder me = new Folder("me");
d.add(code);
code.add(company);
code.add(me);
Folder projectA = new Folder("projectA");
File classA1 = new File("classA1");
projectA.add(classA1);
Folder projectB = new Folder("projectB");
File classB1 = new File("classB1");
projectB.add(classB1);
company.add(projectA);
company.add(projectB);
Folder myProject = new Folder("myProject");
File excelA = new File("excelA.xls");
me.add(myProject);
me.add(excelA);
d.operation();
}
}
实现效果,由于主要是体现组合模式,因此没有实现结构划分: