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.
应用组合模式之后,不论是统计员工、子部门还是大部门的人数和薪资,都可以通过统一的接口——
count
和getSalary
方法获取,非常简单。
代码地址
写在最后
如果你觉得我写的文章帮到了你,欢迎点赞、评论、分享、赞赏哦,你们的鼓励是我不断创作的动力~
网友评论