一、定义
职责链模式,就是将能够处理某类请求事件的一些处理类,类似链条的串联起来。请求在链条上处理的时候,并不知道具体是哪个处理类进行处理的。一定程度上实现了请求和处理的解耦。
实际生活中的经典例子就是公司的报销流程,一般主管、经理、总经理都是不同的报销额度,当职员进行报销申请的时候,如果主管权限不足,会自动的再向上提交给经理,经理可以处理也可以再向上
提交总经理。报销申请(请求事件)提交后,职员自己并不需要再关注谁能处理,只是关注到最后结果即可。
二、java代码示例
示例中,就以简单的逐层报销为例子:
申请请求类:
package com.cfang.chainTest; import lombok.Builder;
import lombok.Data; @Data
@Builder
public class ApplyFile { private String name;
private Integer money; }
抽象处理类:
package com.cfang.chainTest; import lombok.Data;
import lombok.NonNull; @Data
public abstract class HandleCls { protected HandleCls nextCls;
@NonNull
private String name; //处理节点名 public abstract void pro(ApplyFile applyFile);
}
主管类(直接审批,负责接收和向上申请)
package com.cfang.chainTest; public class ZhuGuan extends HandleCls{ public ZhuGuan(String name) {
super(name);
}
@Override
public void pro(ApplyFile applyFile) {
if(applyFile.getMoney() < 100) {
System.out.println(this.getName() + "处理了申请:" + applyFile.toString());
}else {
this.nextCls.pro(applyFile);
}
} }
经理类:
package com.cfang.chainTest; public class JingLi extends HandleCls{ public JingLi(String name) {
super(name);
}
@Override
public void pro(ApplyFile applyFile) {
if(applyFile.getMoney() < 200) {
System.out.println(this.getName() + "处理了申请:" + applyFile.toString());
}else {
this.nextCls.pro(applyFile);
}
} }
总经理类:
package com.cfang.chainTest; public class ZoneJingLi extends HandleCls{ public ZoneJingLi(String name) {
super(name);
}
@Override
public void pro(ApplyFile applyFile) {
if(applyFile.getMoney() < 300) {
System.out.println(this.getName() + "处理了申请:" + applyFile.toString());
}else {
this.nextCls.pro(applyFile);
}
} }
测试类:审批流程链条是自己进行设置的,供使用者进行调用。
package com.cfang.chainTest; public class TestMain { public static void main(String[] args) {
//创建职责链条
HandleCls p1 = new ZhuGuan("主管");
HandleCls p2 = new JingLi("经理");
HandleCls p3 = new ZoneJingLi("总经理");
p1.setNextCls(p2);
p2.setNextCls(p3); //创建报销申请
ApplyFile applyFile = ApplyFile.builder().name("猪小屁").money(99).build();
p1.pro(applyFile); applyFile = ApplyFile.builder().name("猪小屁").money(101).build();
p1.pro(applyFile); applyFile = ApplyFile.builder().name("猪小屁").money(201).build();
p1.pro(applyFile);
}
}
输出:
主管处理了申请:ApplyFile(name=猪小屁, money=99)
经理处理了申请:ApplyFile(name=猪小屁, money=101)
总经理处理了申请:ApplyFile(name=猪小屁, money=201)
三、实际应用场景
java类加载机制、servlet filter过滤器链、mybatis的plugin机制。。。
四、总结
优点:
1、请求对象不需要具体知道哪个类去处理,只需要关注最后处理结果即可。
2、新增一个处理类的时候,无需修改原有代码,只需要维护处理器链即可
缺点:
1、调用的时候,不明确一定能处理,可能会出现到最后都没处理(一般可以设计个兜底服务)
2、建立链条的时候,如果设置不当,可能形成循环调用。