最近看了一些开源的软件,发现人家的代码写的很漂亮,设计的也很好,于是乎,我便默默的把买来还没看的设计模式之禅拿来,补补基础。
书本上介绍的模式类型很多,自己见得比较多的可能就是单例、工厂等几个。今天先从组合模式开始,就是随手翻到了这个,也不是书本介绍的第一个。
组合模式:我的理解就是要解决类似于机构或者文件目录等形式的树状结构图,节点之前既有相同特性,又有差异。节点之前是相互隶属关系,这个隶属关系也很重要,如一个家族中族谱也是一个典型的案例。通过使用组合模式,我们可以方便的存储这样一个结构信息,同时有很松散的新增或者删除其中一个节点,遍历这样一个图谱也是easy的。
实现该场景的一个经典类图关系
所有的节点都继承基类component,其中Leaf类是指代那些最底层节点,没有子节点的节点。composite类指代含有子节点的节点信息。之所有细分两种情况,因为有些操作,在叶子节点中是禁止的。比如add,remove;
根据书中的理论,还有一种不安全的实现方法,这种方法就是去掉叶子节点,所有节点都一样,但是要求基类的所有方法都抛一个异常,这样叶子节点就在调用时检查到异常。
下面,我来根据一个场景实现下组合模式。比如公司有ceo一名,两个经理managera,mangerb,两个收下分别两个小兵
employeaa,employeeab,employeeba,employeebb,实现这样组织结构的存储和遍历。
首先是抽象类staff:
package com.stone.patter.composite;
public class Staff {
protected String name;
protected int salary;
protected String position;
public Staff(String name, int salary, String position) {
this.name = name;
this.salary = salary;
this.position = position;
}
protected void addStaff(Staff staff) {
throw new RuntimeException("非法操作:addStaff");
}
protected void removeStaff(Staff staff) {
throw new RuntimeException("非法操作:removeStaff");
}
protected void printInfo() {
System.out.println("名字:" + name + " ,职位:" + position + " ,薪水:" + salary);
}
}
其次分别编写经理、CEO、小喽喽:
package com.stone.patter.composite;
import java.util.ArrayList;
import java.util.List;
public class Manager extends Staff {
private List<Staff> staffs = new ArrayList<>();
public Manager(String name, int salary, String position) {
super(name, salary, position);
}
@Override
protected void addStaff(Staff staff) {
staffs.add(staff);
}
@Override
protected void removeStaff(Staff staff) {
staffs.remove(staff);
}
@Override
protected void printInfo() {
super.printInfo();
for (Staff staff : staffs) {
staff.printInfo();
}
}
}
package com.stone.patter.composite;
public class Employee extends Staff {
public Employee(String name, int salary, String position) {
super(name, salary, position);
}
}
测试类
package com.stone.patter.composite;
public class Client {
public static void main(String[] args) {
Staff ceo = new Manager("执行官1", 100000, "CEO");
Staff managera = new Manager("经理1", 10000, "经理");
Staff managerb = new Manager("经理2", 10000, "经理");
Staff empaa = new Manager("小喽喽1", 1000, "职员");
Staff empab = new Manager("小喽喽2", 1000, "职员");
Staff empba = new Manager("小喽喽3", 1000, "职员");
Staff empbb = new Manager("小喽喽4", 1000, "职员");
managera.addStaff(empaa);
managera.addStaff(empab);
managerb.addStaff(empba);
managerb.addStaff(empbb);
ceo.addStaff(managera);
ceo.addStaff(managerb);
ceo.printInfo();
}
}
测试结果
名字:执行官1 ,职位:CEO ,薪水:100000
名字:经理1 ,职位:经理 ,薪水:10000
名字:小喽喽1 ,职位:职员 ,薪水:1000
名字:小喽喽2 ,职位:职员 ,薪水:1000
名字:经理2 ,职位:经理 ,薪水:10000
名字:小喽喽3 ,职位:职员 ,薪水:1000
名字:小喽喽4 ,职位:职员 ,薪水:1000