1. 什么是责任链模式
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
举个例子,SpringMvc 中可以定义拦截器,并且可以定义多个。当一个用户发起请求时,顺利的话请求会经过所有拦截器,最终到达业务代码逻辑,SpringMvc 拦截器设计就是使用了责任链模式
在责任链模式中,多个处理器(参照上述拦截器)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条,链条上的每个处理器 各自承担各自的处理职责
责任链模式中多个处理器形成的处理器链在进行处理请求时,有两种处理方式:
请求会被 所有的处理器都处理一遍,不存在中途终止的情况,这里参照 MyBatis 拦截器理解。

二则是处理器链执行请求中,某一处理器执行时,如果不符合自制定规则的话,停止流程,并且剩下未执行处理器就不会被执行,大家参照 SpringMvc 拦截器理解

这里通过代码的形式对两种处理方式作出解答,首先看下第一种,请求会经过所有处理器执行的情况。
IHandler 负责抽象处理器行为,handle() 则是不同处理器具体需要执行的方法,HandleA、HandleB 为具体需要执行的处理器类,HandlerChain 则是将处理器串成一条链执行的处理器链。
1 2 3 4 5 6 7 8 9 10 11 12
| public class ChainApplication { public static void main(String[] args) { HandlerChain handlerChain = new HandlerChain(); handlerChain.addHandler(Lists.newArrayList(new HandlerA(), new HandlerB())); handlerChain.handle();
} }
|
这种责任链执行方式会将所有的 处理器全部执行一遍,不会被打断。MyBatis 拦截器用的正是此类型,这种类型 重点在对请求过程中的数据或者行为进行改变
而另外一种责任链模式实现,则是会对请求有阻断作用,阻断产生的前置条件是在处理器中自定义的,代码中的实现较简单
根据代码看的出来,在每一个 IHandler 实现类中会返回一个布尔类型的返回值,如果返回布尔值为 false,那么责任链发起类会中断流程,剩余处理器将不会被执行。就像我们定义在 SpringMvc 中的 Token 拦截器,如果 Token 失效就不能继续访问系统,处理器将请求打回
1 2 3 4 5 6 7 8 9 10
| public class ChainApplication { public static void main(String[] args) { HandlerChain handlerChain = new HandlerChain(); handlerChain.addHandler(Lists.newArrayList(new HandlerA(), new HandlerB())); boolean resultFlag = handlerChain.handle(); if (!resultFlag) { System.out.println("责任链中处理器不满足条件"); } } }
|
应用场景
在实际应用中,责任链模式常用于请求的预处理、请求的过滤、请求的分发等场景。例如,可以使用责任链模式来实现权限校验、日志记录、异常处理、请求重试等功能。同时,也可以将责任链模式与其他设计模式结合起来,例如装饰器模式、工厂模式、观察者模式等,从而实现更复杂的功能
2. 责任链模式结构
抽象处理者(Handler)角色:声明处理请求的所有接口,包含抽象处理方法,持有对下一个处理者的引用
基础处理者(Base Handler)角色:「是一个可选的类」, 可以将所有处理者共用的样本代码放置在其中
- 当使用基础处理者时,抽象处理者只需要定义行为方法。持有对下一个处理者的引用「下放到基础处理者」
- 可以在基础处理者实现一些具体处理者的公共方法,避免代码冗余
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法。判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者
客户类(Client):创建处理链,并向链头的具体处理者对象提交请求
优点和缺点
优点在于,它可以动态地添加、删除和调整处理者对象,从而灵活地构建处理链。同时,它也避免了请求发送者和接收者之间的紧耦合,增强了系统的灵活性和可扩展性。
不过,责任链模式也有一定的缺点,例如如果处理链过长或者处理时间过长,可能会对系统性能产生一定的影响
3. 自定义一个责任链模式
需求
假设有一个学校有一个采购审批的需要,采购项目需要给领导审批,不同金钱范围,对应的审批领导的等级不同,如下:
- 金额小于5000,由教学主任审批
- 金额小于等于5000,由院长审批
- 金额小于等于30000,由副校长任审批
- 金额大于30000,由校长审批
构成的责任链
编码实现
定义实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class ApproverRequest { private int type = 0; private float price = 0.0f; private int id = 0; public ApproverRequest(int type, float price, int id) { this.type = type; this.price = price; this.id = id; } public int getType() { return type; } public float getPrice() { return price; } public int getId() { return id; } }
|
在写一个抽象类,用于定义全局,作为子类的规范。链条中所有的结点都需要继承子类,实现子类里面的抽象方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
@Component public abstract class Approver { Approver next ; String name ;
public Approver(String name){ this.name = name; }
public void setNext(Approver next) { this.next = next; }
public abstract void processApprover(ApproveRequest approveRequest); }
|
写链条中的第一个结点,由教学主任负责审批。如果金额太大,教学主任审批不了,那么就由这个院长审批
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class DepartmentApprover extends Approver { public DepartmentApprover(String name){ super(name); } @Override public void processApprover(ApproverRequest approveRequest) { if(approveRequest.getPrice() <= 5000) { System.out.println(" 请求编号 id= " + approveRequest.getId() + " 被 " + this.name + " 处理"); }else { next.processApprover(approveRequest); } }
}
|
然后链条中的第二个结点,由院长负责审批。如果金额太大,院长审批不了,那么就由这个副校长审批
1 2 3 4 5 6 7 8 9 10 11
| public class CollegeApprover extends Approver{ public CollegeApprover(String name) {super(name); } @Override public void processApprover(ApproverRequest approveRequest) { if(approveRequest.getPrice() > 5000 && approveRequest.getPrice() <= 10000) { System.out.println(" 请求编号 id= " + approveRequest.getId() + " 被 " + this.name + " 处理"); }else { next.processApprover(approveRequest); } } }
|
然后链条中的第三个结点,由副长负责审批。如果金额太大副校长审批不了,那么就由这个校长审批
1 2 3 4 5 6 7 8 9 10 11 12
| public class ViceSchoolMasterApprover extends Approver{ public ViceSchoolMasterApprover(String name) {super(name); } @Override public void processApprover(ApproverRequest approveRequest) { if(approveRequest.getPrice() > 10000 && approveRequest.getPrice() <= 30000) { System.out.println(" 请求编号 id= " + approveRequest.getId() + " 被 " + this.name + " 处理"); }else { next.processApprover(approveRequest); } } }
|
然后开始写最后一个结点,由校长审批
1 2 3 4 5 6 7 8 9 10 11
| public class SchoolMasterApprover extends Approver{ public SchoolMasterApprover(String name) {super(name); } @Override public void processApprover(ApproverRequest approveRequest) { if(approveRequest.getPrice() > 30000) { System.out.println(" 请求编号 id= " + approveRequest.getId() + " 被 " + this.name + " 处理"); }else { next.processApprover(approveRequest); } } }
|
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class Main { public static void main(String[] args) { ApproverRequest approveRequest = new ApproverRequest(1, 20000, 1); DepartmentApprover departmentApprover = new DepartmentApprover("刘主任"); CollegeApprover collegeApprover = new CollegeApprover("刘院长"); ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("刘副校"); SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("刘校长");
departmentApprover.setNext(collegeApprover); collegeApprover.setNext(viceSchoolMasterApprover); viceSchoolMasterApprover.setNext(schoolMasterApprover); schoolMasterApprover.setNext(departmentApprover);
departmentApprover.processApprover(approveRequest); } }
|
本文参考的文章:
http://t.csdnimg.cn/R5vsi
http://t.csdnimg.cn/I42xf
http://t.csdnimg.cn/71wZO