责任链模式
责任链模式:解耦请求传递与处理的设计艺术
一、责任链模式的核心定义
责任链模式(Chain of Responsibility Pattern) 是一种行为型设计模式,它将请求的发送者与接收者解耦,通过构建 “处理者链条”,让请求在链条中依次传递,直到某个处理者能够处理该请求为止。其核心思想是:每个处理者只负责自己职责范围内的请求,无法处理则传递给下一个处理者,链条上的处理者无需知道请求的最终处理者是谁,实现请求处理的灵活分发。
简单来说,责任链模式就像公司的售后客服流程 —— 用户反馈问题(请求),先由一线客服处理(初级处理者),无法解决则转交给技术支持(中级处理者),仍无法解决则提交给产品经理(高级处理者),直到问题被处理,每个环节只需专注自己能处理的问题,无需关心后续流转。
二、责任链模式的核心结构
责任链模式包含三个关键角色,链条结构清晰,职责分工明确:
-
抽象处理者(Handler):定义处理请求的统一接口,包含一个指向 “下一个处理者” 的引用(构成链条的核心),以及处理请求的抽象方法。
-
具体处理者(Concrete Handler):实现抽象处理者接口,判断自身是否能处理当前请求 —— 能处理则直接处理,不能处理则调用下一个处理者的处理方法,将请求传递下去。
-
请求对象(Request):封装需要处理的请求信息(如请求类型、内容、优先级等),供处理者判断是否能处理。
结构示意图(简化):
Request(请求对象)
↓
Handler(抽象处理者)
↑
├───────┬───────┬───────┤
HandlerA(处理者A)→ HandlerB(处理者B)→ HandlerC(处理者C)
(初级处理) (中级处理) (高级处理)
三、责任链模式的代码实现
以 “电商售后问题处理” 为例:用户的售后请求分为三类 —— 咨询问题(如使用方法)、退货申请、投诉问题,分别由客服专员、售后专员、客服主管依次处理,形成责任链。
1. 请求对象(AfterSaleRequest)
封装售后请求的核心信息,供处理者判断处理权限:
// 售后请求类
public class AfterSaleRequest {
private String requestType; // 请求类型:咨询/退货/投诉
private String content; // 请求内容
private int priority; // 优先级(1-低,2-中,3-高)
// 构造方法
public AfterSaleRequest(String requestType, String content, int priority) {
this.requestType = requestType;
this.content = content;
this.priority = priority;
}
// getter方法(省略setter,请求信息不可修改)
public String getRequestType() { return requestType; }
public String getContent() { return content; }
public int getPriority() { return priority; }
}
2. 抽象处理者(AfterSaleHandler)
定义处理请求的统一接口,包含下一个处理者的引用和处理方法:
// 抽象售后处理者
public abstract class AfterSaleHandler {
protected AfterSaleHandler nextHandler; // 下一个处理者(构成链条)
// 设置下一个处理者(链式组装)
public void setNextHandler(AfterSaleHandler nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请求的抽象方法(子类必须实现)
public abstract void handleRequest(AfterSaleRequest request);
}
3. 具体处理者(Concrete Handler)
实现不同层级的售后处理逻辑,判断是否能处理请求并决定是否传递:
// 1. 客服专员(处理咨询类请求)
public class CustomerService extends AfterSaleHandler {
@Override
public void handleRequest(AfterSaleRequest request) {
// 只处理“咨询”类型的请求
if ("咨询".equals(request.getRequestType())) {
System.out.println("【客服专员】处理咨询请求:");
System.out.println("请求内容:" + request.getContent());
System.out.println("处理结果:已解答用户疑问n");
} else {
// 无法处理,传递给下一个处理者
if (nextHandler != null) {
System.out.println("【客服专员】无法处理" + request.getRequestType() + "请求,转交给售后专员n");
nextHandler.handleRequest(request);
} else {
System.out.println("【客服专员】无后续处理者,请求无法处理n");
}
}
}
}
// 2. 售后专员(处理退货类请求)
public class RefundSpecialist extends AfterSaleHandler {
@Override
public void handleRequest(AfterSaleRequest request) {
// 只处理“退货”类型的请求
if ("退货".equals(request.getRequestType())) {
System.out.println("【售后专员】处理退货请求:");
System.out.println("请求内容:" + request.getContent());
System.out.println("优先级:" + (request.getPriority() == 3 ? "高" : "中/低"));
System.out.println("处理结果:已受理退货申请,将在3个工作日内退款n");
} else {
// 无法处理,传递给下一个处理者
if (nextHandler != null) {
System.out.println("【售后专员】无法处理" + request.getRequestType() + "请求,转交给客服主管n");
nextHandler.handleRequest(request);
} else {
System.out.println("【售后专员】无后续处理者,请求无法处理n");
}
}
}
}
// 3. 客服主管(处理投诉类请求)
public class CustomerManager extends AfterSaleHandler {
@Override
public void handleRequest(AfterSaleRequest request) {
// 只处理“投诉”类型的请求
if ("投诉".equals(request.getRequestType())) {
System.out.println("【客服主管】处理投诉请求:");
System.out.println("请求内容:" + request.getContent());
System.out.println("优先级:" + (request.getPriority() == 3 ? "高(加急处理)" : "中/低"));
System.out.println("处理结果:已记录投诉内容,将联系用户协商解决方案n");
} else {
// 无法处理,传递给下一个处理者(若有)
if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("【客服主管】无后续处理者,请求无法处理n");
}
}
}
}
4. 客户端调用(测试代码)
组装责任链,发送不同类型的请求,验证链条处理逻辑:
public class Client {
public static void main(String[] args) {
// 1. 创建具体处理者
AfterSaleHandler customerService = new CustomerService(); // 客服专员
AfterSaleHandler refundSpecialist = new RefundSpecialist(); // 售后专员
AfterSaleHandler customerManager = new CustomerManager(); // 客服主管
// 2. 组装责任链:客服专员 → 售后专员 → 客服主管
customerService.setNextHandler(refundSpecialist);
refundSpecialist.setNextHandler(customerManager);
// 3. 发送请求1:咨询请求(由客服专员处理)
AfterSaleRequest consultRequest = new AfterSaleRequest(
"咨询", "如何查询物流信息?", 1
);
System.out.println("=== 处理请求1 ===");
customerService.handleRequest(consultRequest);
// 4. 发送请求2:退货请求(由售后专员处理)
AfterSaleRequest refundRequest = new AfterSaleRequest(
"退货", "商品质量问题,申请退货", 2
);
System.out.println("=== 处理请求2 ===");
customerService.handleRequest(refundRequest);
// 5. 发送请求3:投诉请求(由客服主管处理)
AfterSaleRequest complaintRequest = new AfterSaleRequest(
"投诉", "客服态度恶劣,要求道歉", 3
);
System.out.println("=== 处理请求3 ===");
customerService.handleRequest(complaintRequest);
// 6. 发送请求4:未知类型请求(链条末端无法处理)
AfterSaleRequest unknownRequest = new AfterSaleRequest(
"换货", "商品尺码不合适,申请换货", 2
);
System.out.println("=== 处理请求4 ===");
customerService.handleRequest(unknownRequest);
}
}
5. 运行结果
=== 处理请求1 ===
【客服专员】处理咨询请求:
请求内容:如何查询物流信息?
处理结果:已解答用户疑问
=== 处理请求2 ===
【客服专员】无法处理退货请求,转交给售后专员
【售后专员】处理退货请求:
请求内容:商品质量问题,申请退货
优先级:中/低
处理结果:已受理退货申请,将在3个工作日内退款
=== 处理请求3 ===
【客服专员】无法处理投诉请求,转交给售后专员
【售后专员】无法处理投诉请求,转交给客服主管
【客服主管】处理投诉请求:
请求内容:客服态度恶劣,要求道歉
优先级:高(加急处理)
处理结果:已记录投诉内容,将联系用户协商解决方案
=== 处理请求4 ===
【客服专员】无法处理换货请求,转交给售后专员
【售后专员】无法处理换货请求,转交给客服主管
【客服主管】无后续处理者,请求无法处理
四、责任链模式的核心优势
-
解耦请求发送与处理:请求发送者只需将请求传递给链条的第一个处理者,无需知道后续谁来处理、如何处理,降低组件间的耦合。
-
灵活调整处理流程:可通过增减处理者、修改处理者顺序来调整责任链(如新增 “换货专员” 插入链条),符合开闭原则。
-
增强代码扩展性:新增处理逻辑时,只需新增具体处理者类并加入链条,无需修改原有处理者代码。
-
简化对象职责:每个处理者只关注自己能处理的请求,职责单一,代码简洁易维护。
五、责任链模式的应用场景
-
请求需要多环节处理:如审批流程(请假审批:员工→部门经理→HR→总经理)、售后处理、异常处理(系统异常:业务异常→系统异常→兜底异常处理)。
-
请求处理者不明确:请求可能由多个处理者中的一个处理,但发送者不确定具体是谁(如用户反馈可能由客服、技术、运营等不同角色处理)。
-
需要动态调整处理流程:如工作流引擎(可配置审批节点顺序)、日志过滤链(按顺序执行不同的日志过滤规则)。
-
框架中的应用:Java 的
Filter接口(Servlet 过滤器链)、Spring 的HandlerInterceptor(请求拦截器链)、MyBatis 的Interceptor(插件拦截链)。
六、使用注意事项
-
避免链条过长:链条过长会导致请求处理效率降低(需依次传递),且排查问题困难,建议控制处理者数量(一般不超过 5 个)。
-
防止循环引用:若处理者之间相互引用(如 A→B→A),会导致请求无限循环传递,需在组装链条时校验。
-
确保请求有终点:需确保每个请求都能被链条中的某个处理者处理,或在链条末端设置 “默认处理者”(如兜底处理逻辑),避免请求丢失。
-
处理者的无状态设计:建议具体处理者为无状态(不存储实例变量),可复用同一个处理者对象,减少内存占用。

浙公网安备 33010602011771号