设计模式的代码:https://github.com/Aerozb/design_patterns
目录
概念
责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。
案例
编写程序完成学校OA系统的采购审批项目:需求
- 采购员采购教学器材
- 如果金额小于等于5000, 由教学主任审批
- 如果金额小于等于10000, 由院长审批
- 如果金额小于等于30000, 由副校长审批
- 如果金额超过30000以上,有校长审批
传统方案解决OA系统审批问题分析
1) 传统方式是:接收到一个采购请求后,根据采购金额来调用对应的Approver (审批人)完成审批。
2) 传统方式的问题分析 : 客户端这里会使用到 分支判断(比如 switch) 来对不同的采购请求处理, 这样就存在如下问题
- 如果各个级别的人员审批金额发生变化,在客户端的也需要变化
- 客户端必须明确的知道 有多少个审批级别和访问
3) 这样 对一个采购请求进行处理 和Approver (审批人) 就存在强耦合关系,不利于代码的扩展和维护
4) 解决方案 =》 职责链模式
UML类图
实现代码
/**
* 教学器材购买请求
*/
public class EquipmentPurchaseRequest {
//请求的金额
private BigDecimal price;
//请求id
private int id;
public int getId() {
return id;
}
public BigDecimal getPrice() {
return price;
}
public EquipmentPurchaseRequest(BigDecimal price, int id) {
this.price = price;
this.id = id;
}
}
/**
* 抽象审批者
*/
public abstract class Approver {
//下一个处理审批的人
Approver approver;
//审批人名字
String name;
public Approver(String name) {
this.name = name;
}
public void setApprover(Approver approver) {
this.approver = approver;
}
//子类做具体处理审批对的方法
public abstract void processRequest(EquipmentPurchaseRequest epr);
}
/**
* 教导主任
*/
public class Director extends Approver {
public Director(String name) {
super(name);
}
@Override
public void processRequest(EquipmentPurchaseRequest epr) {
if (epr.getPrice().compareTo(BigDecimal.valueOf(5000))<=0) {
System.out.println("请求编号:"+epr.getId()+"被"+name+"处理");
}else {
approver.processRequest(epr);
}
}
}
/**
* 院长
*/
public class Dean extends Approver {
public Dean(String name) {
super(name);
}
@Override
public void processRequest(EquipmentPurchaseRequest epr) {
if (epr.getPrice().compareTo(BigDecimal.valueOf(5000))>=0&&epr.getPrice().compareTo(BigDecimal.valueOf(10000))<=0) {
System.out.println("请求编号:"+epr.getId()+" 被"+name+"处理");
}else {
approver.processRequest(epr);
}
}
}
/**
* 副校长
*/
public class VicePrincipal extends Approver{
public VicePrincipal(String name) {
super(name);
}
@Override
public void processRequest(EquipmentPurchaseRequest epr) {
if (epr.getPrice().compareTo(BigDecimal.valueOf(10000))>=0&&epr.getPrice().compareTo(BigDecimal.valueOf(30000))<=0) {
System.out.println("请求编号:"+epr.getId()+"被"+name+"处理");
}else {
approver.processRequest(epr);
}
}
}
/**
* 校长
*/
public class Principal extends Approver {
public Principal(String name) {
super(name);
}
@Override
public void processRequest(EquipmentPurchaseRequest epr) {
if (epr.getPrice().compareTo(BigDecimal.valueOf(30000))>=0) {
System.out.println("请求编号:"+epr.getId()+"被"+name+"处理");
}else {
approver.processRequest(epr);
}
}
}
public class Client {
public static void main(String[] args) {
//创建一个器材购买请求
EquipmentPurchaseRequest epr = new EquipmentPurchaseRequest(BigDecimal.valueOf(30001),1234);
//创建审批人
Director director = new Director("主任");
Dean dean = new Dean("院长");
VicePrincipal vp = new VicePrincipal("副校长");
Principal p = new Principal("校长");
//设置下一个审批人,最后一个审批人也要设置下一个,进行一个圆圈循环审批,回到原点,防止不懂从哪个审批人开始,然后没处理到
director.setApprover(dean);
dean.setApprover(vp);
vp.setApprover(p);
p.setApprover(director);
//开始请求审批
director.processRequest(epr);
}
}
结果
请求编号:1234 被校长处理
如果没有责任链模式,我们可能会把所有的逻辑写在一处,里面堆积着一堆if….else,这样是违反“单一职责原则”的,就算我们把这些逻辑拆分为多个类,假如后期增加或删除某些节点,或者调整节点顺序,就要修改源码,进行严格测试。而使用了责任链模式,很好地解决了这个设计问题。