组合模式
什么是组合模式
在讲解组合模式之前,我们先来看一下它的定义
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
我们还是通过一个小例子来帮助我们理解组合模式的意义:我们的电脑中都有文件资源管理器(就是文件夹),文件资源管理器由目录和具体的文件组成,每个目录下都拥有属于自己的文件或者子目录,每个文件里又装着属于自己的内容。那么目录就相当于是由单个对象(即具体文件)或组合对象(即子目录)构成的,如果在开发应用软件时需要描述类似这样的树形数据结构,那么就可以选择使用组合模式。
组合模式在我们处理树型结构的问题时,帮助我们模糊了简单元素和复杂元素的概念,也就是将对象组合成树形结构来表示“部分-整体”的层次结构,那么程序可以像处理简单元素一样来处理复杂元素(也就是对单个对象和组合对象的操作具有一致性),从而使得程序与复杂元素的内部结构之间达到解耦。
组合模式的实现
我们再说一个和我们息息相关的小例子,每一位小伙伴所在的公司都有很多同事,他们有的是领导,有的是普通的员工,无论是领导还是员工都有自己的上级或下级(当然了,董事长这种大BOSS就没有上级了)。接下来我们就用代码来简单实现一下这个例子
创建一个员工类
import java.util.ArrayList;
import java.util.List;
/**
* 员工类
* @description: Employee
* @author: 庄霸.liziye
* @create: 2022-04-10 21:49
**/
public class Employee {
/**
* 员工姓名
*/
private String name;
/**
* 员工岗位
*/
private String post;
/**
* 下级员工
*/
private List<Employee> subordinates;
/**
* 构造方法
*/
public Employee(String name,String post) {
this.name = name;
this.post = post;
subordinates = new ArrayList<Employee>();
}
public void add(Employee e) {
subordinates.add(e);
}
public void remove(Employee e) {
subordinates.remove(e);
}
public List<Employee> getSubordinates(){
return subordinates;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", post='" + post + '\'' +
", subordinates=" + subordinates +
'}';
}
}
复制代码
通过员工类来创建并打印员工的层次结构
/**
* @description: Test
* @author: 庄霸.liziye
* @create: 2022-04-10 22:03
**/
public class Test {
public static void main(String[] args) {
Employee CEO = new Employee("张三","董事长");
Employee leader1 = new Employee("李四","研发主管");
Employee leader2 = new Employee("王五","销售总管");
Employee programmer1 = new Employee("小明","Java程序员");
Employee programmer2 = new Employee("小刚","C++程序员");
Employee sales1 = new Employee("小红","销售");
Employee sales2 = new Employee("小芳","销售");
CEO.add(leader1);
CEO.add(leader2);
leader1.add(programmer1);
leader1.add(programmer2);
leader2.add(sales1);
leader2.add(sales2);
//打印该组织的所有员工
System.out.println(CEO);
for (Employee headEmployee : CEO.getSubordinates()) {
System.out.println(headEmployee);
for (Employee employee : headEmployee.getSubordinates()) {
System.out.println(employee);
}
}
}
}
复制代码
组合模式的优、缺点
最后我们总结一下组合模式的优点与缺点
优点
高层模块(就像上面代码中的CEO)调用简单。组合模式让客户端(即 main 方法)代码可以一致的处理单个对象和组合对象,并不需要再耗费精力去关心自己处理的是单个对象还是组合对象,这也就帮助我们简化了客户端代码;同时节点可以自由增加,更容易在组合体内加入新的对象,客户端也不会因为加入了新的对象而更改源代码,满足了“开闭原则”;
缺点
在使用组合模式时,节点和其子节点的声明都是实现类,而不是接口去声明,这也违反了依赖倒置原则;而且使用组合模式会导致代码设计变得更复杂,客户端需要花更多时间去梳理类之间的层次关系;