cover

Chain of Responsibility 模式:請求接力

Chain of Responsibility 模式把請求一路傳給下一個處理者,直到有人處理為止。

classDiagram
    class Handler {
        <<abstract>>
        -nextHandler : Handler
        +setNext(handler) Handler
        +handle(request)* any
    }
    class StockHandler {
        +handle(request) any
    }
    class DiscountHandler {
        +handle(request) any
    }
    class PaymentHandler {
        +handle(request) any
    }
    Handler <|-- StockHandler
    Handler <|-- DiscountHandler
    Handler <|-- PaymentHandler
    Handler --> Handler : nextHandler

使用情境

  1. 購物車結帳:庫存 → 折扣 → 付款。
  2. 事件處理:依事件類型逐層處理。
  3. 權限驗證:多層檢核規則。

實作範例

Chain of Responsibility 模式:請求依序通過檢查關卡

class Handler {
  constructor() {
    this.nextHandler = null;
  }
 
  setNext(handler) {
    this.nextHandler = handler;
    return handler;
  }
 
  handle(request) {
    if (this.nextHandler) {
      return this.nextHandler.handle(request);
    }
    return null;
  }
}
 
class StockHandler extends Handler {
  handle(request) {
    if (request.quantity > 100) {
      console.log('Stock check failed: quantity too large');
      return { success: false, message: 'Out of stock' };
    }
    console.log('Stock check passed');
    return super.handle(request);
  }
}
 
class DiscountHandler extends Handler {
  handle(request) {
    if (request.amount > 1000) {
      request.discount = 0.1;
      console.log('10% discount applied');
    }
    return super.handle(request);
  }
}
 
class PaymentHandler extends Handler {
  handle(request) {
    if (!request.paymentMethod) {
      console.log('Payment failed: no payment method');
      return { success: false, message: 'Payment required' };
    }
    console.log('Payment processed successfully');
    return { success: true, message: 'Order completed' };
  }
}
 
const stockHandler = new StockHandler();
const discountHandler = new DiscountHandler();
const paymentHandler = new PaymentHandler();
 
stockHandler.setNext(discountHandler).setNext(paymentHandler);
 
const order = { quantity: 5, amount: 1500, paymentMethod: 'credit_card' };
const result = stockHandler.handle(order);
console.log(result);

優點

  • 降低耦合
  • 處理流程可動態調整
  • 易於新增節點

缺點

  • 請求可能沒人處理
  • 鏈過長時難除錯

延伸閱讀