設計模式之責任鏈模式

王若伊_恩赐解脱發表於2024-08-22

責任鏈模式是物件導向的23種設計模式中的一種,屬於行為模式範圍。
責任鏈模式(Chain of Responsibility),
見名知意:就是每一個處理請求的處理器組合成一個連結串列,連結串列中的每個節點(執行器)都有機會處理傳送的請求。

大致的結構是這個樣子:


舉一個簡單的例子:
某公司有一名新員工要入職,則入職過程大致分為三步:
1、簽訂勞動合同
2、員工資訊入庫
3、下發工卡
我們按照責任鏈模式的思路來設計這塊業務:

類圖如下:

程式碼如下:

處理器介面

1 package com.example.demo.learn.pattern.behavior.responsibilitychain;
2 
3 public interface IHandler {
4     boolean handle(Employee employee);
5 }

合同處理器

 1 package com.example.demo.learn.pattern.behavior.responsibilitychain;
 2 
 3 /**
 4  * @discription
 5  */
 6 public class CardHandler implements IHandler{
 7     @Override
 8     public boolean handle(Employee employee) {
 9         System.out.println("製作工牌:工號"+employee.getId()+" 姓名:"+employee.getName());
10         return true;
11     }
12 }

協議處理器

 1 package com.example.demo.learn.pattern.behavior.responsibilitychain;
 2 
 3 /**
 4  * @discription
 5  */
 6 public class ContractHandler implements IHandler {
 7     @Override
 8     public boolean handle(Employee employee) {
 9         System.out.println("簽訂合同:" + employee);
10         return true;
11     }
12 }

系統流程處理器

 1 package com.example.demo.learn.pattern.behavior.responsibilitychain;
 2 
 3 import java.util.Date;
 4 
 5 /**
 6  * @discription
 7  */
 8 public class SystemHandler implements IHandler {
 9     @Override
10     public boolean handle(Employee employee) {
11         long id = new Date().getTime();
12         employee.setId(id);
13         System.out.println("員工資訊登入到系統中: " + employee);
14         return true;
15     }
16 }

員工類:業務實體

 1 package com.example.demo.learn.pattern.behavior.responsibilitychain;
 2 
 3 import lombok.Data;
 4 
 5 /**
 6  * @discription
 7  */
 8 @Data
 9 public class Employee {
10     private Long id;
11     private String name;
12 }

主類:責任鏈的編排和請求呼叫

 1 package com.example.demo.learn.pattern.behavior.responsibilitychain;
 2 
 3 /**
 4  * @discription
 5  */
 6 public class PatternMain {
 7     public static void main(String[] args) {
 8         ContractHandler contractHandler = new ContractHandler();
 9         SystemHandler systemHandler = new SystemHandler();
10         CardHandler cardHandler = new CardHandler();
11 
12 
13         EntryChain entry = new EntryChain(contractHandler, systemHandler, cardHandler);
14         String name = "小z";
15         boolean result = entry.process(name);
16         if (result) {
17             System.out.println(name + "的入職流程已經處理完");
18         }
19     }
20 }

執行效果如下:

Connected to the target VM, address: '127.0.0.1:63269', transport: 'socket'
簽訂合同:Employee(id=null, name=小z)
員工資訊入庫: Employee(id=1724316937102, name=小z)
製作工牌:工號1724316937102 姓名:小z
小z的入職流程已經全部處理完
Disconnected from the target VM, address: '127.0.0.1:63269', transport: 'socket'

來具體說下設計的核心思路:

首先我們需要定義好一個介面,這個介面規範每一個執行器(責任鏈節點)的執行方法。在本例中就是IHandler介面。
接著我們定義3個實現類(也就是所謂的執行器,即責任鏈的節點),(防盜連線:本文首發自http://www.cnblogs.com/jilodream/ )每個執行器中實現介面的方法,編寫當前執行器要做的事。
最後我們需要一個連結串列來編排當前各個執行器的執行順序。
當我們將請求下發,系統就可以按照責任鏈編排的順序,依次執行了。
有些文章也這樣定義:
抽象介面---->抽象處理器(Handler)角色
具體執行器實現---->具體處理者(ConcreteHandler)角色

責任鏈模式一般應用在:
1、流程編排(如電子流工單處理)
2、資源的使用(依次申請資源--->使用資源--->釋放資源)
3、日誌記錄、許可權過濾、請求預處理 (如在aop切面程式設計執行順序的編排)

那麼為啥要搞責任鏈模式呢?
我們直接從頭到尾寫一套流程不就行了麼,這樣還比較直接,易懂。
如果是簡單的使用,那麼肯定是可以的,但是如果要是業務流程複雜,又經常變動,以滿足開閉原則為初衷,則從頭到尾寫一套流程就很難維護了。
所以我們可以將各個執行節點(執行器)為物件,按照具體場景,隨意的調整順序,隨意的增加新的場景。從這個角度看,是不是逐漸就有了一點物件導向的意思。

設計模式除了舉得這個簡單的例子外,還有很多的變形:
1、有些場景將責任鏈的節點,儲存在每一個責任鏈節點的next引用處,(防盜連線:本文首發自http://www.cnblogs.com/jilodream/ )從而形成一個邏輯上的單連結串列結構,而不是依賴某一個list來儲存。
2、責任鏈模式既可以從中途結束返回,也可以依次的每個節點都執行,這個沒有強制的約束。
3、責任鏈模式是一個整體的設計思路,並不是某幾個固定方法,比如我們的OA流程,就是一個大的流程,可能跨多個服務,並不是某幾個方法簡單編排一下就可以的。
那麼我們應該怎麼掌握呢?個人覺得設計模式本來就是一個設計思路,沒必要條條框框,按部就班的來。要根據核心思路,以實際情況為場景,來靈活的實現和使用。

相關文章