JavaScript 责任链模式 (Chain of Responsibility)

75 阅读2分钟

模式定义

责任链模式允许将请求沿着处理链传递,直到有一个处理者能够处理该请求。每个处理者决定是否处理请求传递给下一个处理者,从而实现请求发送者与接收者的解耦。


核心场景

  • 多级审批流程(如报销审批:员工 → 经理 → 财务)
  • 请求过滤(如 API 请求的权限校验、日志记录、参数检查)
  • 事件冒泡机制(DOM 事件处理)
  • 中间件架构(如 Express.js 的中间件栈)

模式结构

  • Handler:定义处理请求的接口,通常包含 setNexthandle 方法
  • ConcreteHandler:具体处理者,实现处理逻辑,决定是否处理或传递请求
  • Client:创建责任链并向链头发送请求

JavaScript 实现示例

场景:订单处理链(验证 → 库存检查 → 支付)

// 抽象处理者基类
class OrderHandler {
  constructor() {
    this.nextHandler = null;
  }

  setNext(handler) {
    this.nextHandler = handler;
    return handler; // 支持链式调用
  }

  handle(order) {
    if (this.nextHandler) {
      return this.nextHandler.handle(order);
    }
    return null; // 链尾处理
  }
}

// 具体处理者:订单验证
class OrderValidationHandler extends OrderHandler {
  handle(order) {
    if (!order.productId || order.amount <= 0) {
      throw new Error("Invalid order details");
    }
    console.log("Order validated successfully");
    return super.handle(order);
  }
}

// 具体处理者:库存检查
class InventoryCheckHandler extends OrderHandler {
  handle(order) {
    const hasStock = checkInventory(order.productId, order.amount);
    if (!hasStock) {
      throw new Error("Insufficient stock");
    }
    console.log("Stock available");
    return super.handle(order);
  }
}

// 具体处理者:支付处理
class PaymentHandler extends OrderHandler {
  handle(order) {
    if (!processPayment(order.paymentMethod, order.total)) {
      throw new Error("Payment failed");
    }
    console.log("Payment processed successfully");
    return super.handle(order);
  }
}

// 客户端使用
const order = {
  productId: "123",
  amount: 2,
  paymentMethod: "credit_card",
  total: 100
};

// 构建责任链
const validator = new OrderValidationHandler();
const inventory = new InventoryCheckHandler();
const payment = new PaymentHandler();

validator.setNext(inventory).setNext(payment);

try {
  validator.handle(order); // 触发链式处理
  console.log("Order processed successfully!");
} catch (error) {
  console.error("Order failed:", error.message);
}

模式优势

  1. 解耦:请求发送者无需知道具体处理者
  2. 动态扩展:可灵活增删处理者或调整顺序
  3. 单一职责:每个处理者专注自己的逻辑

适用性提醒

  • 适合处理流程中存在多个潜在处理者的场景
  • 避免处理链过长导致性能问题(可结合熔断机制)
  • 明确每个处理者的责任边界,防止循环调用

实际应用案例

  1. Express 中间件:多个中间件按顺序处理 HTTP 请求
  2. 表单验证链:依次检查字段格式、长度、业务规则
  3. 游戏事件处理:UI 事件 → 角色响应 → 场景更新