設計模式 —— 責任鏈模式

鐵鏽的秀發表於2019-03-26

簡介

責任鏈模式(Chain of Responsibility Pattern)使多個物件都有機會處理請求,從而避免了請求的傳送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。

例項

責任鏈模式包含一下角色:

  1. Handler: 抽象處理者。定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類或者Java介面實現。
  2. ConcreteHandler:具體處理者。具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
  3. Client:客戶類

下面我們以一個簡單的請假作為示例。假設請假一天,專案經理處理就能處理,三天之類歸專案總監處理,七天內歸老闆處理,請假不允許超過七天。 抽象處理者

public abstract class AbstractHandler {
    /**
     * 下一個處理物件
     */
    private AbstractHandler next;
    /**
     * 處理請假
     *
     * @param leaveDays 天數
     * @return 處理結果
     */
    public final String handleLeave(int leaveDays) {
        if (this.getLeaveDays() >= leaveDays) {
            return this.handle();
        } else {
            if (Objects.nonNull(next)) {
                return next.handleLeave(leaveDays);
            } else {
                return "大老闆都不能處理你的假期了~~";
            }
        }
    }
    /**
     * 具體處理
     *
     * @return 處理結果
     */
    protected abstract String handle();

    /**
     * 每個處理類能處理的天數,資料可以使資料庫獲取,這裡簡單就寫死了
     *
     * @return 請假天數
     */
    protected abstract Integer getLeaveDays();

    /**
     * 設定下一個處理類
     *
     * @param next
     */
    public void setNext(AbstractHandler next) {
        this.next = next;
    }
}
複製程式碼

具體處理者

// 專案經理處理
public class PMHandler extends AbstractHandler {

    @Override
    protected String handle() {
        return "你的請假被專案經理處理了";
    }

    @Override
    protected Integer getLeaveDays() {
        return 1;
    }
}

// 專案總監處理
public class PDHandler extends AbstractHandler {
    @Override
    protected String handle() {
        return "你的請假被專案總監處理了";
    }

    @Override
    protected Integer getLeaveDays() {
        return 3;
    }
}

// 大老闆處理
public class BossHandler extends AbstractHandler {
    @Override
    protected String handle() {
        return "你的請假被大老闆處理了";
    }

    @Override
    protected Integer getLeaveDays() {
        return 7;
    }
}
複製程式碼

客戶端

@Test
public void test() {
    PMHandler pmHandler = new PMHandler();
    PDHandler pdHandler = new PDHandler();
    BossHandler bossHandler = new BossHandler();

    pmHandler.setNext(pdHandler);
    pdHandler.setNext(bossHandler);

    String leaveRes = pmHandler.handleLeave(1);
    System.out.println(leaveRes);
    String leaveRes1 = pmHandler.handleLeave(3);
    System.out.println(leaveRes1);
    String leaveRes2 = pmHandler.handleLeave(7);
    System.out.println(leaveRes2);
    String leaveRes3 = pmHandler.handleLeave(8);
    System.out.println(leaveRes3);
}
複製程式碼

類圖

責任鏈模式

優點

  1. 降低耦合度。它將請求的傳送者和接收者解耦;
  2. 簡化了物件。使得物件不需要知道鏈的結構;
  3. 增強給物件指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任;
  4. 增加新的請求處理類很方便。

缺點

  1. 請求沒有明確的接收者,不能保證它一定會被處理,該請求可能一直到鏈的末端都得不到處理;
  2. 對於比較長的職責鏈,請求的處理可能涉及到多個處理物件,系統效能將受到一定影響,而且在進行程式碼除錯時不太方便,可能會造成迴圈呼叫。

適用場景

  1. 有多個物件可以處理同一個請求,具體哪個物件處理該請求由執行時刻自動確定;
  2. 在不明確指定接收者的情況下,向多個物件中的一個提交一個請求;
  3. 可動態指定一組物件處理請求。

總結

責任鏈模式有兩種使用形式:純責任鏈模式和不純的責任鏈模式。

如果一個類要麼承擔責任處理請求要麼將請求踢給下一個皮球,則被稱為純責任鏈模式;如果一個類承擔了一部分責任,還將請求踢給下一個皮球,則被稱為不純的責任鏈模式。純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現。

相關文章