2292 字
约 7 分钟
2
责任链设计模式(Chain of Responsibility Pattern)

责任链设计模式(Chain of Responsibility Pattern)

1. 什么是责任链模式?

责任链模式是一种行为型设计模式

核心思想:

将多个处理节点按照顺序组织成一条链,请求依次经过每个节点,由每个节点决定是否继续向下执行。

简单理解:

一个任务需要经过多个环节:

请求

 ↓

节点1

 ↓

节点2

 ↓

节点3

 ↓

完成

每个节点:

  • 处理自己的业务
  • 修改上下文数据
  • 决定是否继续执行

例如请假流程:

员工提交请假

       ↓

MT审批

       ↓

LD审批

       ↓

大LD审批

       ↓

最终结果

每个人都是责任链上的一个节点。


2. 为什么需要责任链模式?

2.1 没有责任链的问题

假设请假流程:

实习生请假:

需要:

MT同意

↓

LD同意

↓

大LD同意

代码可能:

public boolean requestLeave(User user){

    if(!mtApprove(user)){

        return false;

    }


    if(!ldApprove(user)){

        return false;

    }


    if(!ldldApprove(user)){

        return false;

    }


    return true;

}

刚开始没问题。

但是流程变化:

新增:

HR审批

部门负责人审批

老板审批

代码:

if(){

}

if(){

}

if(){

}

if(){

}

if(){

}

问题:

  • 流程代码越来越长
  • 每新增一个节点都需要修改原代码
  • 节点之间耦合严重

3. 责任链模式解决什么问题?

责任链模式将:

流程控制

业务节点

拆开。

结构:

             ProcessController

                    |

                    ↓

 ------------------------------------------------

 MT审批        LD审批        大LD审批       HR审批


流程控制器负责:

按照顺序执行节点

每个节点负责:

自己的业务逻辑

4. 责任链核心组成

责任链通常包含四个部分:


① 上下文 Context

负责保存链路中的数据。

例如:

请假流程:

User user

审批结果:

needBreak

代码:

public class ProcessContext<T extends ProcessModel>{


    // 责任链标识
    private String code;


    // 业务数据
    private T processModel;


    // 是否终止链路
    private Boolean needBreak = false;



}

为什么需要 Context?

因为责任链中的每个节点需要共享数据。

例如:

MT节点

修改审批状态


↓

LD节点

读取审批状态

继续处理

② 统一流程接口

所有节点实现:

public interface BusinessProcess<T extends ProcessModel>{


    void process(ProcessContext<T> context);


}

作用:

保证所有节点:

输入一致

执行方式一致

③ 业务节点

例如:

审批节点:

public abstract class Authority 
        implements BusinessProcess<User>{


    protected boolean requestLeave(User user)
            throws Exception{


        throw new Exception(
            "没有权限"
        );

    }



    @Override
    public void process(
        ProcessContext<User> context
    ){


        try{

            boolean result =
                requestLeave(
                    context.getProcessModel()
                );


            // 是否继续执行
            context.setNeedBreak(!result);


        }catch(Exception e){


            context.setNeedBreak(true);

        }

    }

}

父类负责:

统一流程

子类负责:

具体审批逻辑

MT节点

public class MT extends Authority{


    @Override
    protected boolean requestLeave(User user){


        System.out.println(
            "MT同意请假"
        );


        return true;

    }

}

LD节点

public class LD extends Authority{


    @Override
    protected boolean requestLeave(User user){


        System.out.println(
            "LD同意请假"
        );


        return true;

    }

}

大LD节点

public class LDLD extends Authority{


    @Override
    protected boolean requestLeave(User user){


        System.out.println(
            "大LD同意请假"
        );


        return true;

    }

}

5. 责任链执行器

责任链核心:

负责:

  • 保存节点
  • 按顺序执行
  • 判断是否中断
public class ProcessController {


    private List<BusinessProcess> processList;



    public ProcessContext process(
        ProcessContext context
    ){


        for(
            BusinessProcess process:
            processList
        ){


            process.process(context);



            // 是否终止
            if(context.getNeedBreak()){


                break;

            }

        }


        return context;

    }


}

6. 使用责任链

public class Main {


    public static void main(String[] args){


        User user =
            new User("xhy");


        ProcessContext<User> context =
            new ProcessContext<>();


        context.setProcessModel(user);



        ProcessController controller =
            new ProcessController();



        controller.setProcessList(
            Arrays.asList(
                new MT(),
                new LD(),
                new LDLD()
            )
        );


        controller.process(context);



        if(context.getNeedBreak()){


            System.out.println(
                "请假失败"
            );


            return;

        }


        System.out.println(
            "请假成功"
        );

    }

}

执行:

MT同意请假

LD同意请假

大LD同意请假

请假成功

7. 责任链模式和模板模式区别

很多人第一次看责任链会疑惑:

不就是多个任务按顺序执行吗?模板模式也可以。

确实类似。

但是两者解决的问题不同。


模板模式

核心:

固定流程,部分步骤交给子类实现。

结构:

父类


固定流程

    |
    ↓

子类实现步骤

例如:

文件上传:

上传流程:

1. 校验文件

2. 上传

3. 记录日志

不同存储:

上传本地

上传OSS

上传服务器

流程固定。


责任链模式

核心:

多个节点组成流程,每个节点可以决定是否继续。

结构:

节点1

 ↓

节点2

 ↓

节点3

 ↓

节点4

特点:

  • 节点数量可变化
  • 节点顺序可调整
  • 节点可以中断
  • 节点可以动态增加

例如:

审批流程:

员工

↓

主管

↓

经理

↓

总监


8. 两者核心区别

模板模式 责任链模式
关注点 流程固定 任务编排
控制者 父类 链路控制器
节点关系 继承关系 组合关系
流程变化 较少变化 动态变化
是否可以中断 通常不能 可以
是否动态添加节点 困难 容易
适合 固定流程 审批/过滤/处理链

简单理解:

模板模式:

我规定流程,你实现步骤。

责任链:

我有很多处理节点,谁处理由链路决定。


9. 责任链模式什么时候使用?

判断标准:

条件1:一个请求需要经过多个处理阶段

例如:

订单创建:

参数校验

↓

库存检查

↓

价格计算

↓

优惠计算

↓

订单生成

适合责任链。


条件2:处理节点可能动态变化

例如:

风控:

黑名单检查

↓

风险评分

↓

人工审核

↓

短信验证

不同业务:

可能:

增加节点

删除节点

调整顺序

适合责任链。


条件3:某个节点可以终止流程

例如:

权限校验:

登录检查

↓

权限检查

↓

业务执行

如果:

没有权限:

直接结束。


10. 常见应用场景

① Spring MVC HandlerInterceptor

Spring MVC 拦截器本质就是责任链。

请求流程:

HTTP请求

   ↓

登录拦截器

   ↓

权限拦截器

   ↓

日志拦截器

   ↓

Controller

每个拦截器:

可以:

  • 执行前置逻辑
  • 执行后置逻辑
  • 中断请求

例如:

preHandle(){

    return false;

}

直接终止后续流程。


② Tomcat Filter

过滤器链:

Request

 ↓

EncodingFilter

 ↓

AuthFilter

 ↓

LogFilter

 ↓

Servlet

每个 Filter:

可以:

chain.doFilter()

继续执行。

也可以:

直接返回。


③ RPC 框架

RPC 请求:

请求

↓

参数校验

↓

限流

↓

负载均衡

↓

序列化

↓

发送请求

↓

日志记录

每一步:

都是责任链节点。


④ 任务编排系统

例如:

订单流程:

创建订单

↓

扣库存

↓

扣余额

↓

发送通知

↓

完成订单

每个任务:

一个节点。


11. 责任链 + 模板模式

实际项目中经常一起使用。

例如:

责任链负责:

节点顺序

节点组合

流程控制

模板负责:

单个节点内部固定流程

例如:

订单审核:

责任链:

风险审核

↓

库存审核

↓

金额审核

每个审核节点内部:

模板:

参数校验

↓

业务处理

↓

记录结果

组合:

责任链控制大流程

模板控制单节点流程

12. 总结

责任链模式核心:

将多个有状态处理节点按照顺序组合,请求依次经过节点,每个节点处理自己的逻辑,并决定是否继续执行。

解决:

  • 大量流程判断
  • 多阶段处理
  • 动态流程编排
  • 可中断业务流程

适合:

  • 审批流程
  • Spring MVC拦截器
  • Tomcat Filter
  • RPC调用链
  • 风控流程
  • 任务编排

一句话总结:

责任链模式就是把复杂流程拆成多个独立节点,通过链路组合完成任务编排,让每个节点只关注自己的职责。

在中间件和框架源码中,经常看到:

工厂负责创建节点

责任链负责组织流程

模板负责节点内部执行

这三个设计模式组合起来,是很多组件化系统的核心设计方式。

责任链设计模式(Chain of Responsibility Pattern)
http://clxhxhhr.top/posts/380/
作者
clxstart
发布于
2026-09-01
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。