目录
前言
是一种 行为型设计模式,它通过将请求沿着一条处理链传递,直到某个对象处理它为止。这种模式的核心思想是 解耦请求的发送者和接收者,使多个对象都有机会处理请求,避免请求发送者与具体处理者之间的紧耦合。
核心思想是将请求的处理职责沿着对象链传递,而不明确指定具体哪个对象处理。
如下图所示:
这种模式特别适用于需要多级处理的场景,例如工作流管理系统、审批流程、过滤器链等。
如下图所示:
1、责任链模式概念
主要目的是解耦请求的发送者和接收者,使得多个对象都有机会处理请求。
1.1、定义介绍
职责链模式是一种行为型设计模式,它允许将请求沿着一个处理链传递,直到链中的某个对象处理它。
将链中的每一个结点看做是一个对象,每个结点处理请求均不同,且内部自动维护一个下一个结点对象。当请求从链条的首端出发时,会沿着链的路径依次传递给每一个结点的对象,直到有对象处理这个请求为止。
每个结点会处理一件事情,如果结点间出现异常,那么链路就会中断。
1.2、流程图
如下图所示:
1.3、优缺点
1、优点:
降低耦合度:请求发送者与处理者解耦,发送者不需要知道具体哪个处理者会处理请求。
动态组合:可以灵活地修改责任链的结构,增加或减少处理器。
职责分离:将请求处理的各个步骤分散到不同的处理者中,符合单一职责原则。
2、缺点:
可能无处理结果:如果链上的所有处理者都不能处理该请求,那么该请求将被丢弃。
性能问题:责任链过长可能会影响系统性能,因为请求会依次传递给链上的每一个处理者。
2、实现
在Java中,职责链模式通常通过定义一个抽象处理器类来实现,该类包含处理请求的方法以及持有下一个处理器的引用。
如下图所示:
代码示例:
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(Request request);
}
具体的处理器类继承自这个抽象类,并根据自己的能力决定是否处理请求或将其传递给下一个处理器。
代码示例:
class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getLevel() == 1) {
System.out.println("ConcreteHandler1 handled the request.");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getLevel() == 2) {
System.out.println("ConcreteHandler2 handled the request.");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
测试:
class Request {
private int level;
public Request(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
public class ChainOfResponsibilityPatternExample {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setNextHandler(handler2);
Request request1 = new Request(1);
Request request2 = new Request(2);
handler1.handleRequest(request1);
handler1.handleRequest(request2);
}
}
3、应用场景
责任链模式适用于需要将请求的处理逻辑分散到多个对象中的场景。
例如,在Java的Servlet中,当一个HTTP请求到达服务器时,可能需要经过多个Filter的处理,这种场景就可以使用职责链模式来实现。
此外,职责链模式还可以用于实现工作流管理系统、审批流程等需要多级处理的场景。
在Spring MVC中,HandlerInterceptor
接口允许开发者在请求处理的不同阶段插入自定义逻辑。
3.1、Springmvc流程
这个springMvc的执行流程来说,全部流程就组成了一个链条。每一个步骤就是一个结点,每个结点都会有对应的处理方法,每个结点处理完成之后,就会进入下一个结点。
一旦某个结点出现异常,那么当前的链路就会停止,当前请求中断。
3.2、mybatis的执行流程
mybatis的执行流程也是通过这个责任链模式,首先会创建这个SqlSessionFactory,然后通过这个工厂创建一个SqlSession,这个SqlSession只是一个门面模式,会通过Executer执行增删改查的操作,然后一个Handler用于设置参数,一个Handler用于返回结果集,最后通过这个StatementHandler将执行结果获取。
里面的整个步骤就相当于形成了一个链条,执行完当前结点就会进入下一个结点,如果出现异常,链条终止往下执行。
3.3、Spring的过滤器和拦截器
Spring里面的这个过滤器链路的调用,以及拦截器的链路调用,也是采用这种责任链模式。
3.4、sentinel限流熔断
sentinel里面的每一个规则对应一个槽点,如流控规则,授权规则,熔断规则,热点规则,系统规则等。
里面也是利用这个责任链模式,每个插槽对应一个规则,每个规则处理一个事件。如果出现异常,那么就会进行对应的限流降级。
3.5、aop的加载和使用
aop依赖与ioc,在生产bean并进行实例化之前,先通过bean的第一个后置处理器找到所有在类上面加@AspectJ这个注解的所有类,并在这个类的里面找到所有的befeore,after等注解的方法,每一个before,after等都会生成一个对应的advisor,每个advisor包括advise和pointcut,advise主要是用来作为一个增强器的使用,pointcut是为了进行匹配,匹配成功才进行最终的动态代理的生成。
最后获取到所有的advisors,由于可能有大量的advisor,因此在bean的最后一个后置处理器才对这些所有的advisor进行处理,即在bean进行初始化之后才进行处理。
最后会去循环遍历这些advisors,通过advisors里面封装的pointcut和生成的advisor进行比较,如果匹配成功,则说明bean需要创建动态代理。主要是通过责任链的方式实现。
4、举例
假设有一个学校有一个采购审批的需要,采购项目需要给领导审批,不同金钱范围,对应的审批领导的等级不同,如下:
1、金额小于5000,由教学主任审批
2、金额小于等于5000,由院长审批
3、金额小于等于30000,由副校长任审批
4、金额大于30000,由校长审批
流程图如下:
1、首先定义一个实体类ApproverRequest
/**
*/
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; }
}
2、定义一个抽象类,用于定义全局,作为子类的规范。
链条中所有的结点都需要继承子类,实现子类里面的抽象方法。
/**
* 定义全局
*/
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);
}
3、然后开始写一个链条中的第一个结点,由教学主任负责审批。
如果金额太大,教学主任审批不了,那么就由这个院长审批。
/**
*/
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);
}
}
}
4、然后开始写一个链条中的第二个结点,由院长负责审批。
如果金额太大,院长审批不了,那么就由这个副校长审批
/**
*/
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);
}
}
}
5、然后开始写一个链条中的第三个结点,由副长负责审批。
如果金额太大副校长审批不了,那么就由这个校长审批
/**
*/
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);
}
}
}
6、然后开始写最后一个结点,由校长审批。
/**
*/
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);
}
}
}
7、编写一个测试类
/**
*/
public class Main {
public static void main(String[] args) {
//创建一个请求
ApproverRequest approveRequest = new ApproverRequest(1, 29000, 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);
viceSchoolMasterApprover.processApprover(approveRequest);
}
}
总结
责任链模式通过将请求传递给链上的下一个处理者,解耦了请求发送者和接收者,并且可以根据需要动态组合责任链的结构,使得请求处理更加灵活和可扩展。
参考文章: