責任鏈模式
責任鏈模式(Chain of Responsibility Pattern)是一種行為型設計模式,核心思想是將多個處理請求的對象連成一條鏈,請求沿鏈傳遞直到被處理。它像現實中的“多級審批流程”——請假或報銷時,申請會逐級提交給不同權限的領導,直到有人能處理為止。
一、通俗理解
假設你開發一個多級審批系統:
- 傳統方式:用大量
if-else
判斷不同金額的報銷單由誰審批,代碼臃腫且難以擴展。 - 責任鏈模式:
- 抽象審批人:定義統一的處理接口,并持有下一級審批人的引用。
- 具體審批人(如組長、經理、CEO):各自處理權限內的請求,超出權限則轉交下一級。
最終只需將審批人連成鏈,客戶端提交請求到鏈頭,無需關心具體處理細節。
二、模式結構
- 抽象處理者(Handler):定義處理請求的接口,包含設置下一處理者的方法(如
setNext()
)。 - 具體處理者(ConcreteHandler):實現處理邏輯,若無法處理則轉交下一級。
- 客戶端(Client):創建處理鏈,發起請求。
三、適用場景
- 多級審批流程:如請假、報銷、工單處理。
- 動態擴展處理邏輯:如日志過濾器、權限驗證鏈。
- 請求發送者與接收者解耦:如 GUI 事件傳遞、網絡請求攔截器。
四、代碼實現
1. C++ 示例(報銷審批鏈)
#include <iostream> // 抽象處理者
class Approver {
protected: Approver* next = nullptr;
public: void setNext(Approver* nextApprover) { next = nextApprover; } virtual void handle(int amount) = 0;
}; // 具體處理者:組長
class GroupLeader : public Approver {
public: void handle(int amount) override { if (amount <= 1000) { std::cout << "組長審批通過(金額:" << amount << "元)" << std::endl; } else if (next) { next->handle(amount); } else { std::cout << "無人能處理此金額!" << std::endl; } }
}; // 具體處理者:經理
class Manager : public Approver {
public: void handle(int amount) override { if (amount <= 5000) { std::cout << "經理審批通過(金額:" << amount << "元)" << std::endl; } else if (next) { next->handle(amount); } }
}; int main() { GroupLeader leader; Manager manager; leader.setNext(&manager); leader.handle(800); // 組長處理 leader.handle(3000); // 經理處理 leader.handle(10000); // 無處理 return 0;
}
輸出:
組長審批通過(金額:800元)
經理審批通過(金額:3000元)
無人能處理此金額!
解析:
- 組長處理 ≤1000 元的請求,否則轉交經理。
- 經理處理 ≤5000 元的請求,更高金額無后續處理者。
2. Python 示例(日志過濾器鏈)
from abc import ABC, abstractmethod class LogHandler(ABC): def __init__(self): self.next = None def set_next(self, next_handler): self.next = next_handler @abstractmethod def handle(self, log_level, message): pass class DebugHandler(LogHandler): def handle(self, log_level, message): if log_level == "DEBUG": print(f"[DEBUG] {message}") elif self.next: self.next.handle(log_level, message) class ErrorHandler(LogHandler): def handle(self, log_level, message): if log_level == "ERROR": print(f"[ERROR] {message}") elif self.next: self.next.handle(log_level, message) # 客戶端
debug = DebugHandler()
error = ErrorHandler()
debug.set_next(error) debug.handle("DEBUG", "調試信息") # [DEBUG] 調試信息
debug.handle("ERROR", "系統崩潰") # [ERROR] 系統崩潰
debug.handle("INFO", "普通日志") # 無輸出
解析:
DebugHandler
處理DEBUG
日志,其他級別轉交下一處理者。- 鏈式調用避免硬編碼日志級別判斷。
3. Java 示例(請假審批系統)
// 抽象處理者
abstract class Approver { protected Approver next; public void setNext(Approver next) { this.next = next; } public abstract void handle(int days);
} // 具體處理者:組長
class GroupLeader extends Approver { @Override public void handle(int days) { if (days <= 3) { System.out.println("組長批準請假 " + days + "天"); } else if (next != null) { next.handle(days); } }
} // 具體處理者:經理
class Manager extends Approver { @Override public void handle(int days) { if (days <= 7) { System.out.println("經理批準請假 " + days + "天"); } else if (next != null) { next.handle(days); } }
} public class Client { public static void main(String[] args) { GroupLeader leader = new GroupLeader(); Manager manager = new Manager(); leader.setNext(manager); leader.handle(2); // 組長處理 leader.handle(5); // 經理處理 leader.handle(10); // 無處理 }
}
輸出:
組長批準請假 2天
經理批準請假 5天
解析:
- 組長處理 ≤3 天的請假,其余轉交經理。
- 責任鏈動態組合,新增審批人只需擴展鏈。
五、優缺點分析
優點 | 缺點 |
---|---|
1. 解耦請求與處理邏輯:客戶端無需知道具體處理者 | 1. 性能問題:長鏈可能導致請求傳遞慢 |
2. 靈活擴展:動態增減處理節點,符合開閉原則 | 2. 調試困難:請求可能未被處理或循環傳遞 |
3. 單一職責:每個處理者專注自身邏輯 | 3. 鏈配置錯誤風險:需確保鏈正確連接 |
六、總結
責任鏈模式通過鏈式傳遞請求,實現了處理邏輯的動態組合與解耦。適用于多級審批、日志過濾等場景,但需注意鏈長控制和錯誤處理。其核心價值在于:
- 靈活擴展:新增處理者無需修改原有代碼。
- 職責分離:每個處理者只關注自身任務。
- 實際應用:如 Spring MVC 的攔截器鏈、Netty 的 ChannelPipeline。