责任链模式

责任链模式:解耦请求传递与处理的设计艺术

一、责任链模式的核心定义

责任链模式(Chain of Responsibility Pattern) 是一种行为型设计模式,它将请求的发送者与接收者解耦,通过构建 “处理者链条”,让请求在链条中依次传递,直到某个处理者能够处理该请求为止。其核心思想是:每个处理者只负责自己职责范围内的请求,无法处理则传递给下一个处理者,链条上的处理者无需知道请求的最终处理者是谁,实现请求处理的灵活分发。

简单来说,责任链模式就像公司的售后客服流程 —— 用户反馈问题(请求),先由一线客服处理(初级处理者),无法解决则转交给技术支持(中级处理者),仍无法解决则提交给产品经理(高级处理者),直到问题被处理,每个环节只需专注自己能处理的问题,无需关心后续流转。

二、责任链模式的核心结构

责任链模式包含三个关键角色,链条结构清晰,职责分工明确:

  1. 抽象处理者(Handler):定义处理请求的统一接口,包含一个指向 “下一个处理者” 的引用(构成链条的核心),以及处理请求的抽象方法。

  2. 具体处理者(Concrete Handler):实现抽象处理者接口,判断自身是否能处理当前请求 —— 能处理则直接处理,不能处理则调用下一个处理者的处理方法,将请求传递下去。

  3. 请求对象(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 ===

【客服专员】无法处理换货请求,转交给售后专员

【售后专员】无法处理换货请求,转交给客服主管

【客服主管】无后续处理者,请求无法处理

四、责任链模式的核心优势

  1. 解耦请求发送与处理:请求发送者只需将请求传递给链条的第一个处理者,无需知道后续谁来处理、如何处理,降低组件间的耦合。

  2. 灵活调整处理流程:可通过增减处理者、修改处理者顺序来调整责任链(如新增 “换货专员” 插入链条),符合开闭原则。

  3. 增强代码扩展性:新增处理逻辑时,只需新增具体处理者类并加入链条,无需修改原有处理者代码。

  4. 简化对象职责:每个处理者只关注自己能处理的请求,职责单一,代码简洁易维护。

五、责任链模式的应用场景

  1. 请求需要多环节处理:如审批流程(请假审批:员工→部门经理→HR→总经理)、售后处理、异常处理(系统异常:业务异常→系统异常→兜底异常处理)。

  2. 请求处理者不明确:请求可能由多个处理者中的一个处理,但发送者不确定具体是谁(如用户反馈可能由客服、技术、运营等不同角色处理)。

  3. 需要动态调整处理流程:如工作流引擎(可配置审批节点顺序)、日志过滤链(按顺序执行不同的日志过滤规则)。

  4. 框架中的应用:Java 的Filter接口(Servlet 过滤器链)、Spring 的HandlerInterceptor(请求拦截器链)、MyBatis 的Interceptor(插件拦截链)。

六、使用注意事项

  1. 避免链条过长:链条过长会导致请求处理效率降低(需依次传递),且排查问题困难,建议控制处理者数量(一般不超过 5 个)。

  2. 防止循环引用:若处理者之间相互引用(如 A→B→A),会导致请求无限循环传递,需在组装链条时校验。

  3. 确保请求有终点:需确保每个请求都能被链条中的某个处理者处理,或在链条末端设置 “默认处理者”(如兜底处理逻辑),避免请求丢失。

  4. 处理者的无状态设计:建议具体处理者为无状态(不存储实例变量),可复用同一个处理者对象,减少内存占用。

posted @ 2025-12-06 22:47  圣祖帝皇  阅读(22)  评论(0)    收藏  举报