設計模式——責任鏈模式

gary-liu發表於2017-03-12

模式介紹

責任鏈模式是一種物件的行為模式。在責任鏈模式裡,很多物件由每一個物件對其下家的引用而連線起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任。

模式的優缺點

優點

1.因為客戶端的請求不知道會被哪個物件處理,所以系統的更改可以在不影響客戶端的情況下動態的重新組織和分配責任,這樣靈活性很強。
2.請求傳送者不知道請求會被哪個接收物件處理,且鏈中的物件也不用關心鏈的結構,只需要保持一個指向其後繼者的引用,這樣大大降低了耦合度。

缺點

缺點是沒有明確的接收者,可能傳到鏈的最後,也沒得到正確的處理。

模式結構

模式涉及角色

抽象處理者(Handler)角色:定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類或者Java介面實現。上圖中Handler類的聚合關係給出了具體子類對下家的引用,抽象方法handleRequest()規範了子類處理請求的操作。

具體處理者(ConcreteHandler)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。

結構圖

這裡寫圖片描述

示例

場景

員工請假,請假天數不超過3天,經理可以審批;請假天數超過3天但不超過10天,需要總監批准;請假天數超過10天則需要總經理審批。

類結構分析

請假類:LeaveRequest 包含名稱,請假時間和原因。
管理者抽象類:包含處理請假請求的抽象方法和指定上級的方法。
具體的管理者:實現對請假請求的處理,這裡包括繼承了管理這抽象類的經理類,總監類和總經理類。

程式碼實現

/**
 * 責任鏈模式
 * Created by gary on 2017/3/11.
 */
public class ResponsibilityChainModel {

    public static void main(String[] args){

        LeaveRequest leaveRequest = new LeaveRequest("小劉", 12, "旅遊");

        CommonManager commonManager = new CommonManager("張三");
        Director director = new Director("李四");
        GeneralManager generalManager = new GeneralManager("王五");

        //指定上級關係
        commonManager.setSuperior(director);
        director.setSuperior(generalManager);

        commonManager.handleRequest(leaveRequest);
    }
}

/**
 * 請假請求類
 */
class LeaveRequest{

    private String name;
    private int leaveDays;
    private String reason;

    public LeaveRequest(String name, int leaveDays, String reason){
        this.name = name;
        this.leaveDays = leaveDays;
        this.reason = reason;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getLeaveDays() {
        return leaveDays;
    }

    public void setLeaveDays(int leaveDays) {
        this.leaveDays = leaveDays;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }
}

/**
 * 管理者抽象類
 */
abstract class Manager{

    protected String name;
    protected Manager superior;

    public Manager(String name){
        this.name = name;

    }

    /**
     * 處理請假抽象方法
     */
    public abstract void handleRequest(LeaveRequest leaveRequest);

    public void setSuperior(Manager superior){
        this.superior = superior;
    }
}

/**
 * 經理類,能處理不超過3天的假期
 */
class CommonManager extends Manager{

    public CommonManager(String name){
        super(name);
    }

    public void handleRequest(LeaveRequest leaveRequest){

        int leaveDays = leaveRequest.getLeaveDays();
        if(leaveDays <= 3){
            System.out.println("經理" + name + "批准");
        }else{
            System.out.println("請假超過3天,經理無法處理,交由上級審批");
            if(superior != null){
                superior.handleRequest(leaveRequest);
            }
        }
    }

}

/**
 * 總監類,能處理超過三天但不超過十天的假期
 */
class Director extends Manager{

    public Director(String name){
        super(name);
    }

    public void handleRequest(LeaveRequest leaveRequest){

        int leaveDays = leaveRequest.getLeaveDays();
        if(leaveDays > 3 && leaveDays <= 10){
            System.out.println("總監批准");
        }else{
            System.out.println("請假超過10天,總監無法處理,交由上級審批");
            if(superior != null){
                superior.handleRequest(leaveRequest);
            }
        }
    }

}

/**
 * 總經理類,能處理超過10天以上的假期
 */
class GeneralManager extends Manager{

    public GeneralManager(String name){
        super(name);
    }

    public void handleRequest(LeaveRequest leaveRequest){

        int leaveDays = leaveRequest.getLeaveDays();
        if(leaveDays > 10){
            System.out.println("總經理批准");
        }else{
            if(superior != null){
                superior.handleRequest(leaveRequest);
            }
        }
    }

}

執行結果:

請假超過3天,經理無法處理,交由上級審批
請假超過10天,總監無法處理,交由上級審批
總經理批准

應用場景

java的異常處理,比如異常鏈;Tomcat中的Filter也使用了責任鏈模式

專案中的應用

如果一個類要麼承擔責任處理請求要麼將請求傳遞給下個物件處理,則被稱為純責任鏈模式。
如果一個類承擔了一部分責任,繼續將請求傳遞給下個物件處理,則被稱為不純的責任鏈模式。

專案中可能使用不純的責任鏈模式多一些,比如專案中可以把鏈中的物件做成可配置化,寫到配置檔案中,這樣可以動態指定對那些請求做什麼樣的處理。

參考資料

《JAVA與模式》之責任鏈模式
《大話設計模式》

相關文章