假設今天寫了 code 發 PR (pull request) ,需要兩個 Reviewer ,其中必要 Reviewer 要先核過,再換其他人看完才能併進去分支,此時審核者的判斷可能像這樣:



上面範例除了 if-else 冗長,單一類別有太多責任違反單一職責原則 (SRP) 之外,如果今天要改成兩位必要 Reviewer 才能通過的話,會動到原先條件判斷,也違反開放封閉原則 (OCP)。
當希望多個物件能夠處理相同請求的時候,可以考慮使用責任練模式 (職責鍊模式) 。
基本介紹
In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects.
Chain of Responsibility:
讓多個物件都有機會可以處理請求,避免請求的發送者和接受者之間產生耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞請求,直到有一個物件處理這個請求為止。
來看看結構圖

- Handler: 定義處理 Request 的介面。
- ConcreteHandler: 具體的處理類別,可以存取他的後繼者 (successor),僅處理所負責的 Request,若無法處理便會將 Request 交給此類別的後繼者處理。
- Client: 用戶端程式碼,向鏈上的 ConcreteHandler 提交請求。
程式範例
宣告介面去提供方法定義 next successor 以及各自處理 Request 的邏輯

接著會將每個條件都建立成獨立的 class,去實作 handleRequest 的方法,其中會含有各自的判斷邏輯,以及無法處理時是否要交給下一個 successor。(此部分邏輯略)
接著在 Client 端便可以自定義鏈的順序,這邊可以想像是將每個類別的條件約束一個個串起來,像一條鏈子一樣。

到這邊是不是覺得好像有種熟悉的感覺?這樣不是和狀態模式 (State Pattern) 有點相像,都可以控制物件行為模式嗎?差別如下

總結
優點
- 用戶端可以靈活的增加或修改請求結構,具有彈性。
- 由於客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任。
- 避免掉請求者與接收著的耦合關係。
缺點
- 因為靈活,可能導致一個請求到了鏈的末端都得不到處理,此模式在多次設定的時候很容易出問題。
- 物件處理過多時,會有效能問題,需要謹慎使用。