首先,看一个数据结构:
在平时开发过程中,我们的菜单目录、文件夹目录等都有类似如上的实体结构,其中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();
- }
- }
-
实现效果,由于主要是体现组合模式,因此没有实现结构划分: