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