【设计模式实践系列】组合模式

组合模式

组合模式又叫部分-整体模式,组合模式将对象组合成树的结构,并且让客户端对单个对象和组合对象的使用能够保持一致,组合模式使用的场景不是非常多,但如果一旦数据满足树形结构,那么使用组合模式将会发挥巨大的作用。

主要角色

Component

组合模式中的“根”节点,一般定义为接口或者抽象类,定义了其实现类或者子类的共性内容,并且拥有管理和访问其子部分的方法。

Leaf

组合模式中的“叶子”节点,实现“根”节点定义的方法。

Composite

组合模式中的“子树”节点,实现“根”节点定义的方法。

案例演示

假设我们有一套针对组织机构处理的业务场景,机构下可以挂子机构,另外有每个机构下又会有员工,因此整个数据模型大概如下:

机构表

机构ID上级机构
10
21
31
42

员工表

员工ID所属机构薪资
112000
215000
323000
436000
548000

现在我们需要构建机构、员工组织架构图,并计算每个部门下所有员工的薪资综合。

代码实现

公司

公司就相当于Component角色,有id和salary两个字段,并定义了一个统计公司薪资总和的方法。

public abstract class Company {

    protected long id;
    protected double salary;

    public Company(long id) {
        this.id = id;
    }

    public abstract double calculateSalary();

}

机构

机构就相当于Composite角色,内部维护的companies集合,既可以添加companies,也可以添加leaf,也就是机构可以有下级机构,也可以直接挂员工。

public class Org extends Company {

    private List<Company> companies = new ArrayList<>();

    public Org(long id) {
        super(id);
    }

    @Override
    public double calculateSalary() {
        double totalSalary = 0;
        for (Company company : companies) {
            totalSalary += company.calculateSalary();
        }
        this.salary = totalSalary;
        return totalSalary;
    }

    public void addCompany(Company company) {
        companies.add(company);
    }
}

员工

员工就相当于leaf角色,直接记录每个员工的薪资即可。

public class Employee extends Company {

    private double salary;

    public Employee(long id, double salary) {
        super(id);
        this.salary = salary;
    }

    @Override
    public double calculateSalary() {
        return salary;
    }
}

测试结果

测试案例:

ID为1的机构,下面分别挂了ID为2、3的两个机构,以及ID为1、2的两个员工。
ID为2的机构,挂了ID为4的机构,以及ID为3的员工。
ID为3的机构,挂了ID为4的员工。
ID为4的机构,挂了ID为5的员工。

在这里插入图片描述

public class Main {

    public static void main(String[] args) {
        test();
    }

    private static void test() {

        Org org1 = new Org(1);
        Org org2 = new Org(2);
        Org org3 = new Org(3);
        Org org4 = new Org(4);

        Employee e1 = new Employee(1, 2000);
        Employee e2 = new Employee(2, 5000);
        Employee e3 = new Employee(3, 3000);
        Employee e4 = new Employee(4, 6000);
        Employee e5 = new Employee(5, 8000);

        org1.addCompany(e1);
        org1.addCompany(e2);
        org1.addCompany(org2);
        org1.addCompany(org3);

        org2.addCompany(e3);
        org2.addCompany(org4);

        org3.addCompany(e4);
        org4.addCompany(e5);

        System.out.println("org1 totalSalary: " + calculateSalary(org1));
        System.out.println("org2 totalSalary: " + calculateSalary(org2));
        System.out.println("org3 totalSalary: " + calculateSalary(org3));
        System.out.println("org4 totalSalary: " + calculateSalary(org4));

    }

    private static double calculateSalary(Org org) {
        return org.calculateSalary();
    }

}

输出结果

org1 totalSalary: 24000.0
org2 totalSalary: 11000.0
org3 totalSalary: 6000.0
org4 totalSalary: 8000.0

总结

通过上面的案例可以体会到,组合模式将机构和员工视为一组对象,其中员工为单个对象,机构为组合对象,把他们统一进行处理,利用树结构的特点,递归处理每个“子树”,简化客户端的操作,解耦了复杂对象的处理过程,同时高层模块调用简单,节点增加自由,易于扩展,不过组合模式只适用于类似树形结构的业务数据,实际应用场景有限。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值