設計模式之-職責鏈模式

誰主沉浮oo7發表於2020-09-14

基本概念

  1. 什麼是鏈
  • 鏈是一系列節點的集合。
  • 鏈的各節點可靈活拆分再重組。
  1. 職責鏈模式
  • 使多個物件都有機會處理請求,從而避免請求的傳送者和接受者之間的耦合關係,
  • 將這個物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理他為止。
  1. 角色
  • 抽象處理者角色(Handler):定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類或者Java介面實現。
  • 具體處理者角色(ConcreteHandler):具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
  1. 職責鏈靈活在哪
  • 改變內部的傳遞規則
    在內部,專案經理完全可以跳過人事部到那一關直接找到總經理。
    每個人都可以去動態地指定他的繼任者。
  • 可以從職責鏈任何一關開始。
    如果專案經理不在,可以直接去找部門經理,責任鏈還會繼續,沒有影響。
  • 用與不用的區別
    不用職責鏈的結構,我們需要和公司中的每一個層級都發生耦合關係。
    如果反映在程式碼上即使我們需要在一個類中去寫上很多醜陋的if….else語句。
    如果用了職責鏈,相當於我們面對的是一個黑箱,我們只需要認識其中的一個部門,然後讓黑箱內部去負責傳遞就好了
  1. 純的與不純的責任鏈模式
    一個純的責任鏈模式要求一個具體的處理者物件只能在兩個行為中選擇一個:一是承擔責任,而是把責任推給下家。不允許出現某一個具體處理者物件在承擔了一部分責任後又 把責任向下傳的情況。
    在一個純的責任鏈模式裡面,一個請求必須被某一個處理者物件所接收;在一個不純的責任鏈模式裡面,一個請求可以最終不被任何接收端物件所接收。
    純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現。

示例

  • 程式碼
    1.抽象處理者角色
public abstract class Handler {
    /**
     * 持有後繼的責任物件
     */
    protected Handler successor;
    /**
     * 示意處理請求的方法,雖然這個示意方法是沒有傳入引數的
     * 但實際是可以傳入引數的,根據具體需要來選擇是否傳遞引數
     */
    public abstract void handleRequest();
    /**
     * 取值方法
     */
    public Handler getSuccessor() {
        return successor;
    }
    /**
     * 賦值方法,設定後繼的責任物件
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    
}

2.具體處理者角色

public class ConcreteHandler extends Handler {
    /**
     * 處理方法,呼叫此方法處理請求
     */
    @Override
    public void handleRequest() {
        /**
         * 判斷是否有後繼的責任物件
         * 如果有,就轉發請求給後繼的責任物件
         * 如果沒有,則處理請求
         */
        if(getSuccessor() != null)
        {            
            System.out.println("放過請求");
            getSuccessor().handleRequest();            
        }else
        {            
            System.out.println("處理請求");
        }
    }
 
}

3.客戶端類

public class Client {
 
    public static void main(String[] args) {
        //組裝責任鏈
        Handler handler1 = new ConcreteHandler();
        Handler handler2 = new ConcreteHandler();
        handler1.setSuccessor(handler2);
        //提交請求
        handler1.handleRequest();
    }
}
  • 說明
    可以看出,客戶端建立了兩個處理者物件,並指定第一個處理者物件的下家是第二個處理者物件,而第二個處理者物件沒有下家。然後客戶端將請求傳遞給第一個處理者物件。
    由於本示例的傳遞邏輯非常簡單:只要有下家,就傳給下家處理;如果沒有下家,就自行處理。
    因此,第一個處理者物件接到請求後,會將請求傳遞給第二個處理者物件。由於第二個處理者物件沒有下家,於是自行處理請求。活動時序圖如下所示。

參考

結語

歡迎關注微信公眾號『碼仔zonE』,專注於分享Java、雲端計算相關內容,包括SpringBoot、SpringCloud、微服務、Docker、Kubernetes、Python等領域相關技術乾貨,期待與您相遇!

相關文章