美文网首页设计模式系列篇
设计模式系列篇(十)——组合模式

设计模式系列篇(十)——组合模式

作者: 复旦猿 | 来源:发表于2020-08-27 22:14 被阅读0次

    What

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。正因为其应用场景的特殊性,数据必须能表示成树形结构,这也导致了这种模式在实际的项目开发中并不那么常用。但是,一旦数据满足树形结构,应用这种模式就能发挥很大的作用,能让代码变得非常简洁。

    Why

    组合模式,在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

    How

    比如,有这样一个场景,老板让你统计下员工与部门的人数和薪资,部门的人数(或薪资)等于该部门下所有员工的人数(或薪资)之和,而部门与员工之间存在一个包含关系,部门下面又可以包含很多子部门。我们希望计算员工的人数(或薪资)与计算部门的人数(或薪资)可以用统一方法实现,那么这个需求是特别适合用组合模式来实现。
    接下来,我们就将上面的需求利用组合模式实现出来。
    首先,我们定义接口IEmployee

    public interface IEmployee {
        Integer count();
        Integer getSalary();
    }
    

    然后,我们定义Employee类和Department类,分别实现IEmployee接口。

    public class Employee implements IEmployee{
        private String name;
        private Integer age;
        private Integer salary;
    
        public Employee(String name, Integer age, Integer salary) {
            this.name = name;
            this.age = age;
            this.salary = salary;
        }
    
        @Override
        public Integer count() {
            return 1;
        }
    
        @Override
        public Integer getSalary() {
            return this.salary;
        }
    }
    
    public class Department implements IEmployee{
        private String name;
        private List<IEmployee> employees;
    
        public Department(String name, List<IEmployee> employees) {
            this.name = name;
            this.employees = employees;
        }
    
        @Override
        public Integer count() {
            Integer count = 0;
            for (IEmployee employee : employees) {
                count += employee.count();
            }
            return count;
        }
    
        @Override
        public Integer getSalary() {
            Integer salary = 0;
            for (IEmployee employee : employees) {
                salary += employee.getSalary();
            }
            return salary;
        }
    }
    

    Department类中的 List<IEmployee> employees; 我们既可以传入一个员工列表,我们也可以传入一个部门列表,这就非常灵活了。

    最后,我们来个示例验证下,部门结构在代码里注释出来了,这里就不再赘述。

    public class TestMain {
        public static void main(String[] args) {
            // The department struct is as follows:
            // Data
            // |__DataMining
            // |____Jeremy
            // |____Bob
            // |____Sam
            // |__MachineLearning
            // |____Bill
            // |____Tom
            // |____Amy
            IEmployee employee1 = new Employee("Jeremy", 20, 40000);
            IEmployee employee2 = new Employee("Bob", 21, 30000);
            IEmployee employee3 = new Employee("Sam", 20, 22000);
            List<IEmployee> subDepartment1Employees = new ArrayList<>();
            subDepartment1Employees.add(employee1);
            subDepartment1Employees.add(employee2);
            subDepartment1Employees.add(employee3);
            IEmployee subDepartment1 = new Department("DataMining", subDepartment1Employees);
            System.out.println(String.format("The DataMining subDepartment contains %d employees in total.", subDepartment1.count()));
            System.out.println(String.format("The DataMining subDepartment's salary is %d in total.", subDepartment1.getSalary()));
    
            IEmployee employee4 = new Employee("Bill", 24, 30000);
            IEmployee employee5 = new Employee("Tom", 30, 40000);
            IEmployee employee6 = new Employee("Amy", 24, 20000);
            List<IEmployee> subDepartment2Employees = new ArrayList<>();
            subDepartment2Employees.add(employee4);
            subDepartment2Employees.add(employee5);
            subDepartment2Employees.add(employee6);
            IEmployee subDepartment2 = new Department("MachineLearning", subDepartment2Employees);
            System.out.println(String.format("The MachineLearning subDepartment contains %d employees in total.", subDepartment2.count()));
            System.out.println(String.format("The MachineLearning subDepartment's salary is %d in total.", subDepartment2.getSalary()));
    
            List<IEmployee> subDepartments = new ArrayList<>();
            subDepartments.add(subDepartment1);
            subDepartments.add(subDepartment2);
            IEmployee department = new Department("Data", subDepartments);
            System.out.println(String.format("The Data department contains %d employees in total.", department.count()));
            System.out.println(String.format("The Data department's salary is %d in total.", department.getSalary()));
        }
    }
    

    输出如下:

    The DataMining subDepartment contains 3 employees in total.
    The DataMining subDepartment's salary is 92000 in total.
    The MachineLearning subDepartment contains 3 employees in total.
    The MachineLearning subDepartment's salary is 90000 in total.
    The Data department contains 6 employees in total.
    The Data department's salary is 182000 in total.
    

    应用组合模式之后,不论是统计员工、子部门还是大部门的人数和薪资,都可以通过统一的接口——countgetSalary方法获取,非常简单。

    代码地址

    i-learning

    写在最后

    如果你觉得我写的文章帮到了你,欢迎点赞、评论、分享、赞赏哦,你们的鼓励是我不断创作的动力~

    相关文章

      网友评论

        本文标题:设计模式系列篇(十)——组合模式

        本文链接:https://www.haomeiwen.com/subject/oymhsktx.html