當一個請求可能由多個處理者處理,但發送者不明確知道由誰處理,且處理者集合動態變化時,責任鏈模式提供優雅方案:將處理者串成一條鏈,請求沿鏈傳遞,直到有處理者處理它或到達鏈尾。這避免了發送者與接收者的強耦合,且支援動態新增/移除/重排處理者。本文以「根據訊息長度分級審批」(員工<5字、主管<10字、經理<15字)為例,完整展示責任鏈模式的鏈路構建、請求傳遞與終止機制。
AbstractExecutor,定義 SetSuccessor() 設定下一級、Insert(MessageModel) 處理請求介面,內含 _executor 參考指向下一級。Employee、Leader、Manager,各自實作處理條件與邏輯,若不滿足條件則呼叫 _executor.Insert() 傳遞給下一級。SetSuccessor() 組裝鏈路順序,發起請求給鏈頭。
public abstract class AbstractExecutor
{
protected AbstractExecutor _executor; // 下一級處理者
public void SetSuccessor(AbstractExecutor executor)
{
this._executor = executor;
}
public abstract string Insert(MessageModel mm);
}
關鍵點:_executor 為 protected 允許子類別存取,SetSuccessor() 提供外部組裝鏈路的介面。
Employee(員工):處理長度 < 5 字
public class Employee : AbstractExecutor
{
public override string Insert(MessageModel mm)
{
string rtn = "";
if (mm.Message.Length < 5)
{
SqlMessage m = new SqlMessage();
if (m.Insert(mm))
rtn = "執行者:雇員 內容:" + mm.Message + " 時間:" + mm.PublishTime;
}
else if (base._executor != null)
rtn = _executor.Insert(mm); // 傳遞下一級
return rtn;
}
}
Leader(主管):處理長度 < 10 字
public class Leader : AbstractExecutor
{
public override string Insert(MessageModel mm)
{
string rtn = "";
if (mm.Message.Length < 10)
{
SqlMessage m = new SqlMessage();
if (m.Insert(mm))
rtn = "執行者:主管 內容:" + mm.Message + " 時間:" + mm.PublishTime;
}
else if (base._executor != null)
rtn = _executor.Insert(mm);
return rtn;
}
}
Manager(經理):處理長度 < 15 字,鏈尾處理失敗情況
public class Manager : AbstractExecutor
{
public override string Insert(MessageModel mm)
{
string rtn = "";
if (mm.Message.Length < 15)
{
SqlMessage m = new SqlMessage();
if (m.Insert(mm))
rtn = "執行者:經理 內容:" + mm.Message + " 時間:" + mm.PublishTime;
}
else
rtn = "你所插入的Message不符合要求"; // 鏈尾終止
return rtn;
}
}
AbstractExecutor employee = new Employee();
AbstractExecutor leader = new Leader();
AbstractExecutor manager = new Manager();
employee.SetSuccessor(leader); // 員工 → 主管
leader.SetSuccessor(manager); // 主管 → 經理
// 發起請求給鏈頭
Response.Write(employee.Insert(new MessageModel("abcd", Now))); // 4字 → 員工
Response.Write(employee.Insert(new MessageModel("abcdefgh", Now))); // 8字 → 主管
Response.Write(employee.Insert(new MessageModel("abcdefghigkl", Now))); // 12字 → 經理
Response.Write(employee.Insert(new MessageModel("abcdefghigklmnop", Now))); // 16字 → 拒絕
執行者:雇員 內容:abcd 時間:2007-4-22 20:04:41
執行者:主管 內容:abcdefgh 時間:2007-4-22 20:04:41
執行者:經理 內容:abcdefghigkl 時間:2007-4-22 20:04:41
你所插入的Message不符合要求
完美驗證:請求沿鏈傳遞,首個滿足條件的處理者處理並終止傳遞,超出範圍由鏈尾拒絕。
ChainBuilder 封裝組裝邏輯,支援流式 API:builder.Add().Add().Add().Build() 。IEnumerable<IHandler> 注入)。[HandlerOrder(1)],框架自動排序組裝。SetSuccessor() 檢測是否已在鏈中。NullHandler)避免空參考。| 維度 | 責任鏈 | 中介者 |
|---|---|---|
| 結構 | 線性鏈路 | 星狀中心化 |
| 耦合 | 處理者只知下一級 | 同事只知中介者 |
| 決策 | 分散在各處理者 | 集中在中介者 |
| 適用 | 順序處理、條件分發 | 複雜多對多協調 |
UseMiddleware、Express.js app.use()。責任鏈模式以「鏈路傳遞」取代「條件分發」,將處理邏輯分散至獨立處理者,實現發送者與接收者的解耦與動態組合。本範例以訊息長度分級審批為例,完整展示了抽象處理者定義鏈路結構、具體處理者實作條件判斷與傳遞、客戶端組裝鏈路順序的全流程。實務中,ASP.NET Core Middleware、Java Servlet Filter、Log4j Appender 皆為責任鏈模式的經典應用。掌握此模式,能讓你在設計「多階段處理管道、條件分發路由、插件化擴展點」時,構建出靈活可組合、易於維護擴展的系統架構。