
你去辦護照的經驗是什麼?先到櫃台 A 填表 → 櫃台 B 驗身份 → 櫃台 C 繳費 → 櫃台 D 拍照。每個櫃台只管自己的事,做完就把你傳給下一個。
Chain of Responsibility 就是這種「關卡式」的處理流程。
先講結論
把請求沿著一條「處理鏈」傳遞,每個 handler 決定自己要不要處理、處理完要不要繼續往下傳。你可以動態增減 handler,不用改任何既有的程式碼。
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
實戰:購物車結帳流程
庫存不夠?直接擋掉。庫存 OK?看看有沒有折扣。最後才處理付款。

class Handler {
constructor() { this.nextHandler = null; }
setNext(handler) {
this.nextHandler = handler;
return handler; // 回傳 handler 方便 chain 起來
}
handle(request) {
if (this.nextHandler) return this.nextHandler.handle(request);
return null;
}
}
class StockHandler extends Handler {
handle(request) {
if (request.quantity > 100) {
return { success: false, message: '庫存不足' };
}
console.log('庫存檢查通過');
return super.handle(request);
}
}
class DiscountHandler extends Handler {
handle(request) {
if (request.amount > 1000) {
request.discount = 0.1;
console.log('套用 10% 折扣');
}
return super.handle(request);
}
}
class PaymentHandler extends Handler {
handle(request) {
if (!request.paymentMethod) {
return { success: false, message: '缺少付款方式' };
}
console.log('付款處理完成');
return { success: true, message: '訂單完成' };
}
}
// 串起來
const stock = new StockHandler();
const discount = new DiscountHandler();
const payment = new PaymentHandler();
stock.setNext(discount).setNext(payment);
const result = stock.handle({
quantity: 5,
amount: 1500,
paymentMethod: 'credit_card'
});
// 庫存檢查通過 → 套用 10% 折扣 → 付款處理完成想在庫存檢查後面加一個「黑名單檢查」?寫一個 BlacklistHandler,插進鏈裡就好。其他 handler 完全不用改。
你已經在用了:Express Middleware
Express 的 app.use() 就是 Chain of Responsibility。每個 middleware 做完自己的事,呼叫 next() 傳給下一個。沒呼叫 next() 就停止傳遞。
小心的地方
- 請求可能沒人處理:鏈走完了但沒有任何 handler 處理,要有 fallback
- 鏈太長難 debug:請求經過十個 handler,出問題你要一個一個追
Chain of Responsibility 就像公司的簽核流程——一層一層往上簽,每個人只看自己該看的。問題是鏈條太長的時候,你的請假單要簽到下個月。