Skip to content

组合模式

一、介绍

组合设计模式又叫部分整体模式,将对象组合成树形结构以表示“部分-整体”的层次结构,可以更好的实现管理操作,组合模式使得用户可以使用一致的方法操作单个对象和组合对象。部分-整体对象的基本操作多数是一样的,但是应该还会有不一样的地方

核心:组合模式可以使用一棵树来表示

二、应用场景

  • 银行总行,总行有前台、后勤、网络部门等,辖区下还有地方分行,也有前台、后勤、网络部门,最小的分行就没有子分行了
  • 公司也是,总公司下有子公司,每个公司大部分的部门都类似
  • 文件夹和文件,都有增加、删除等api,也有层级管理关系
  • 当想表达对象的部分-整体的层次结构
  • 当我们的要处理的对象可以生成一颗树形结构,我们要对树上的节点和叶子进行操作时,它能够提供一致的方式,而不用考虑它是节点还是叶子

三、角色

  • 组合部件(Component):它是一个抽象接口,表示树根,例子:总行
  • 合成部件(Composite):和组合部件类似,也有自己的子节点,例子:总行下的分行
  • 叶子(Leaf):在组合中表示子节点对象,注意是没有子节点,例子:最小地方的分行

四、优缺点

  • 优点
    • 客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子的问题
    • 方便创建出复杂的层次结构
  • 缺点
    • 客户端需要花更多时间理清类之间的层次关系

五、代码

抽象接口类Root

package com.lcy.study.design.composite;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Description 根节点
 * @Author lcy
 * @Date 2021/7/22 09:38
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class Root {

    /**
     * 文件名称
     */
    protected String name;

    /**
     * 添加文件
     * @param root 文件对象
     * @author lcy
     * @date 2021/7/23 09:38
     **/
    public abstract void addFile(Root root);

    /**
     * 删除文件
     * @param root 文件对象
     * @author lcy
     * @date 2021/7/23 09:38
     **/
    public abstract void removeFile(Root root);

    /**
     * 显示文件
     * @param depth 深度
     * @author lcy
     * @date 2021/7/23 09:38
     **/
    public abstract void display(int depth);

}

文件夹类Folder

package com.lcy.study.design.composite;

import java.util.ArrayList;
import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @Description 文件夹
 * @Author lcy
 * @Date 2021/7/23 09:40
 */
@AllArgsConstructor
public class Folder extends Root {

    /**
     * 子文件列表
     */
    @Getter
    List<Root> folders = new ArrayList<>();

    public Folder(String name){
        super(name);
    }

    @Override public void addFile(Root root){
        folders.add(root);
    }

    @Override public void removeFile(Root root){
        folders.remove(root);
    }

    @Override public void display(int depth){
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < depth; i++) {
            sb.append(" ");
        }
        //打印横线和当前文件名
        System.out.println(sb + this.getName());
        for (Root r : folders) {
            //每个下级,横线多2个
            r.display(depth + 2);
        }
    }

    public static void main(String[] args){
        Root root = new Folder("root");
        Folder folder1 = new Folder("1");
        Folder folder2 = new Folder("2");
        Folder folder3 = new Folder("3");

        Folder folder11 = new Folder("11");
        Folder folder22 = new Folder("22");
        Folder folder33 = new Folder("33");
        File folder111 = new File("111");
        Folder folder222 = new Folder("222");
        File folder333 = new File("333");
        folder11.addFile(folder111);
        folder22.addFile(folder222);
        folder33.addFile(folder333);
        folder1.addFile(folder11);
        folder2.addFile(folder22);
        folder3.addFile(folder33);
        root.addFile(folder1);
        root.addFile(folder2);
        root.addFile(folder3);

        root.display(0);

    }
}

文件类File

package com.lcy.study.design.composite;

import lombok.AllArgsConstructor;

/**
 * @Description 文件夹
 * @Author lcy
 * @Date 2021/7/23 09:40
 */
@AllArgsConstructor
public class File extends Root {

    public File(String name){
        super(name);
    }

    @Override public void addFile(Root root){

    }

    @Override public void removeFile(Root root){

    }

    @Override public void display(int depth){
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < depth; i++) {
            sb.append(" ");
        }
        //打印横线和当前文件名
        System.out.println(sb.toString() + this.getName());
    }
}