1、组合模式的概念
组合模式,英文Composite Pattern,也称为部分整体模式,属于结构型模式。该模式将一组相似对象当成一个整体对象,使用树形结构来组合对象,来表示部分以及整体层次。该模式创建一个包含自己对象组的类,然后在该类中提供修改相同对象组的方法。
2、组合模式的特点
- 使用树形结构来组合对象。
- 将相似对象组合成一个整体,表示整体和部分层次。
3、关于组合模式
- 使用目的:将对象组合成树形结构来表示整体和部分层次。
- 解决问题:在树形结构中,模糊了简单元素和复杂元素,可以让我们像处理简单元素一样的处理复杂元素,在一定程度上使得客户程序和复杂元素的内部结构解耦。
- 使用时机:
- 想表示对象的整体-部分层次结构时,可以使用树形结构。
- 忽略组合对象和单个对象的不同,统一地使用组合结构中的所有对象。
- 保证组合:树枝和叶子实现统一接口,然后在树枝内部来组合该接口。
- 组合关键:树枝内部组合接口,包含List类型的成员属性,里面封装对象。
4、组合模式的优缺点
优点:
- 高层模块调用简单。
- 节点可以自由增加。
缺点:
- 在组合时,树枝和叶子都是实现类,而不是接口,违反了依赖倒置原则。
5、组合模式的使用场景
- 部分整体层次,比如树形结构,文件夹以及文件的组合形式。
6、组合模式的实现
(1)创建模型类
注意的是,树枝和叶子都是相同类型的对象,使用同一个模型类来定义,如下:
/*
* 组合模型类
* 用来组合相似的一组对象
*/
public class Employee {
// 职务
private String position;
// 员工姓名
private String empName;
// 员工薪水
private double salary;
// 管辖下属,注意这里是一个List类型的成员属性,用来组合该类对象
private List<Employee> subornaties = new ArrayList<>();
// 构造方法
public Employee(String position,String empName,double salary) {
this.position = position;
this.empName = empName;
this.salary = salary;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public List<Employee> getSubornaties() {
return subornaties;
}
public void setSubornaties(List<Employee> subornaties) {
this.subornaties = subornaties;
}
@Override
public String toString() {
return "员工信息=====》[所属职务:" + this.getPosition()
+ ",姓名:" + this.getEmpName()
+ ",薪资:" + this.getSalary() + "]";
}
// 自定义方法,添加员工到List集合中
public void addEmployee(Employee emp) {
subornaties.add(emp);
}
// 从List集合中移除员工
public void delEmployee(Employee emp) {
subornaties.remove(emp);
}
}
(2)测试
public class Test {
public static void main(String[] args){
Employee emp0 = new Employee("公司Boss", "李狗蛋", 50000.0);
Employee emp2 = new Employee("技术部负责人","王尼玛", 20000.0);
Employee emp3 = new Employee("技术部码农","张三", 10000.0);
Employee emp4 = new Employee("技术部码农","李四", 7000.0);
Employee emp5 = new Employee("技术部码农","yanchengzhi", 8000.0);
Employee emp6 = new Employee("销售部负责人", "卖货老王", 30000.0);
Employee emp7 = new Employee("销售部员工", "李永", 15000.0);
Employee emp8 = new Employee("销售部员工", "刘刚", 12000.0);
Employee emp9 = new Employee("人事部负责人", "孙雪", 10000.0);
Employee emp10 = new Employee("人事部员工", "周星星", 8500.0);
Employee emp11 = new Employee("人事部员工", "何晓琳", 7800.0);
// 组合成树形结构
// boss直辖各部门负责人
emp0.addEmployee(emp2);
emp0.addEmployee(emp6);
emp0.addEmployee(emp9);
// 技术部负责人直辖技术部员工
emp2.addEmployee(emp3);
emp2.addEmployee(emp4);
emp2.addEmployee(emp5);
// 销售部负责人直辖销售部员工
emp6.addEmployee(emp7);
emp6.addEmployee(emp8);
// 人事部负责人直辖人事部员工
emp9.addEmployee(emp10);
emp9.addEmployee(emp11);
System.out.println("boss统辖:");
System.out.println("-------------------------------------------------------");
List<Employee> leaders = emp0.getSubornaties();
for(Employee leader:leaders) {
System.out.println(leader.toString());
System.out.println(leader.getPosition() + "统辖:");
List<Employee> employees = leader.getSubornaties();
for(Employee e:employees) {
System.out.println(e.toString());
}
System.out.println("-------------------------------------------------------");
}
}
}
7、小结
组合模式最经典的代表就是树形结构,树枝和叶子节点的组合形式,以及我们电脑上的文件系统,文件夹和具体文件的组合形式。当需要用到整体-部分层次结构时,可以考虑使用组合模式来实现,但是前提是父节点和子节点属于同一类型对象。