責任鏈模式是物件導向的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流程,就是一個大的流程,可能跨多個服務,並不是某幾個方法簡單編排一下就可以的。
那麼我們應該怎麼掌握呢?個人覺得設計模式本來就是一個設計思路,沒必要條條框框,按部就班的來。要根據核心思路,以實際情況為場景,來靈活的實現和使用。