简介

组合模式是一种结构型设计模式,核心是将一组相似对象以树形节点表示,形成“部分-整体”层次。

应用场景

公司后台新增员工入职,员工按级别管理下属,支持添加、删除操作。

结构示意

图1.0 模式结构图
图1.1 代码结构图
图1.2 公司人员结构图

实践

简化代码,叶子与容器合并为 CompanyEmployeeFramework。

@Data
@ToString
class CompanyEmployeeFramework {
    private String employeeName;
    private String title;
    private List<CompanyEmployeeFramework> subordinates;

    CompanyEmployeeFramework(String employeeName, String title) {
        this.employeeName = employeeName;
        this.title = title;
    }

    public void addSubordinates(CompanyEmployeeFramework... subs) {
        if (subordinates == null) subordinates = new ArrayList<>();
        for (CompanyEmployeeFramework s : subs) {
            System.out.println("[" + employeeName + "] => 添加 " + s.employeeName);
        }
        subordinates.addAll(Arrays.asList(subs));
    }

    public void delSubordinates(String name) {
        if (subordinates == null) return;
        Iterator<CompanyEmployeeFramework> it = subordinates.iterator();
        while (it.hasNext()) {
            if (it.next().employeeName.equals(name)) {
                System.out.println("[" + employeeName + "] => 删除 " + name);
                it.remove();
            }
        }
    }

    public static void printTrees(CompanyEmployeeFramework parent) {
        System.out.println(parent.employeeName + "(" + parent.title + ")=>");
        if (parent.subordinates == null) return;
        for (CompanyEmployeeFramework e : parent.subordinates) {
            System.out.println("  姓名:" + e.employeeName + ",职位:" + e.title);
            printTrees(e);
        }
    }
}

客户端

public class CompositeTest {
    public static void main(String[] args) {
        CompanyEmployeeFramework boss = new CompanyEmployeeFramework("John", "Boss");

        CompanyEmployeeFramework m1 = new CompanyEmployeeFramework("王经理", "经理");
        CompanyEmployeeFramework m2 = new CompanyEmployeeFramework("黎经理", "副经理");
        boss.addSubordinates(m1, m2);

        CompanyEmployeeFramework t1 = new CompanyEmployeeFramework("刘总监", "技术总监");
        CompanyEmployeeFramework a1 = new CompanyEmployeeFramework("王明", "架构师");
        m2.addSubordinates(t1, a1);

        CompanyEmployeeFramework e1 = new CompanyEmployeeFramework("小刘", "Java开发");
        CompanyEmployeeFramework e2 = new CompanyEmployeeFramework("小红", "前端开发");
        a1.addSubordinates(e1, e2);

        CompanyEmployeeFramework e3 = new CompanyEmployeeFramework("小明", "UI设计师");
        t1.addSubordinates(e3);

        System.out.println("=== 初始结构 ===");
        CompanyEmployeeFramework.printTrees(boss);

        System.out.println("\n=== 删除后 ===");
        boss.delSubordinates("王经理");
        a1.delSubordinates("小红");
        CompanyEmployeeFramework.printTrees(boss);
    }
}

运行结果

[John] => 添加 王经理
[John] => 添加 黎经理
[黎经理] => 添加 刘总监
[黎经理] => 添加 王明
[王明] => 添加 小刘
[王明] => 添加 小红
[刘总监] => 添加 小明
=== 初始结构 ===
John(Boss)=>
  姓名:王经理,职位:经理
  姓名:黎经理,职位:副经理
    姓名:刘总监,职位:技术总监
      姓名:小明,职位:UI设计师
    姓名:王明,职位:架构师
      姓名:小刘,职位:Java开发
      姓名:小红,职位:前端开发

=== 删除后 ===
[John] => 删除 王经理
[王明] => 删除 小红

总结

组合模式把“个体”与“整体”统一成树形结构,客户端无需区分,适合组织架构、菜单、目录等层次场景。