首頁 > 軟體

Java設計模式之責任鏈模式詳解

2022-07-26 18:03:51

責任鏈(Chain of Responsibility)模式的定義:為了避免請求傳送者與多個請求處理者耦合在一起,於是將所有請求的處理者通過前一物件記住其下一個物件的參照而連成一條鏈;當有請求發生時,可將請求沿著這條鏈傳遞,直到有物件處理它為止。

責任鏈模式的結構

抽象處理者(Handler) 角色:定義一個處理請求的介面,包含抽象處理方法和一個後繼連線。

具體處理者(Concrete Handler)角色:實現抽象處理者的處理方法,判斷能否處理本次請求,如果可以處理請求則處理,否則將該請求轉給它的後繼者。

客戶類(Client) 角色:建立處理鏈,並向鏈頭的具體處理者物件提交請求,它不關心處理細節和請求的傳遞過程。

應用場景

  • 多條件流程判斷許可權控制。
  • ERP系統 流程審批:總經理、人事經理、專案經理。
  • Java過濾器的底層實現Filter
  • 多個物件可以處理一個請求,但具體由哪個物件處理該請求在執行時自動確定。
  • 可動態指定一組物件處理請求,或新增新的處理者。
  • 需要在不明確指定請求處理者的情況下,向多個處理者中的一個提交請求。

優缺點

優點

  • 降低了物件之間的耦合度。該模式使得一個物件無須知道到底是哪一個物件處理其請求以及鏈的結構,傳送者和接收者也無須擁有對方的明確資訊。
  • 增強了系統的可延伸性。可以根據需要增加新的請求處理類,滿足開閉原則。
  • 增強了給物件指派職責的靈活性。當工作流程發生變化,可以動態地改變鏈內的成員或者調動它們的次序,也可動態地新增或者刪除責任。
  • 責任鏈簡化了物件之間的連線。每個物件只需保持一個指向其後繼者的參照,不需保持其他所有處理者的參照,這避免了使用眾多的if或者if.else語句。
  • 責任分擔。每個類只需要處理自己該處理的工作,不該處理的傳遞給下一個物件完成,明確各類的責任範圍,符合類的單一職責原則。

缺點

  • 不能保證每個請求一定被處理。 由於一個請求沒有明確的接收者,所以不能保證它-定會被處理,該請求可能一直傳到鏈的末端都得不到處理。
  • 對比較長的職責鏈,請求的處理可能涉及多個處理物件,系統效能將受到一定影響。
  • 職責鏈建立的合理性要靠使用者端來保證,增加了使用者端的複雜性,可能會由於職責鏈的錯誤設定而導致系統出錯,如可能會造成迴圈呼叫。

程式碼案例

請假條物件

public class LeaveRequest {
    private String name;//姓名
    private int num;//請假天數
    private String content;//請假內容
    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }
    public String getName() {
        return name;
    }
    public int getNum() {
        return num;
    }
    public String getContent() {
        return content;
    }
}

處理者抽象類

public abstract class Handler {
    protected final static int NUM_ONE = 1;
    protected final static int NUM_THREE = 3;
    protected final static int NUM_SEVEN = 7;
    //該領導處理的請假天數區間
    private int numStart;
    private int numEnd;
    //領導上面還有領導
    private Handler nextHandler;
    //設定請假天數範圍 上不封頂
    public Handler(int numStart) {
        this.numStart = numStart;
    }
    //設定請假天數範圍
    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }
    //設定上級領導
    public void setNextHandler(Handler nextHandler){
        this.nextHandler = nextHandler;
    }
    //提交請假條
    public final void submit(LeaveRequest leave){
        if(0 == this.numStart){
            return;
        }
        //如果請假天數達到該領導者的處理要求
        if(leave.getNum() >= this.numStart){
            this.handleLeave(leave);
            //如果還有上級 並且請假天數超過了當前領導的處理範圍
            if(null != this.nextHandler && leave.getNum() > numEnd){
                this.nextHandler.submit(leave);//繼續提交
            } else {
                System.out.println("流程結束");
            }
        }
    }
    //各級領導處理請假條方法
    protected abstract void handleLeave(LeaveRequest leave);
}

繼承抽象類實現責任鏈中各個類中的處理方法

public class Counselor extends Handler {
    public Counselor() {
        //輔導員 處理1-3天的請假
        super(Handler.NUM_ONE, Handler.NUM_THREE);
    }
    @Override
    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("輔導員審批:同意。");
        //也可以在這裡設定下一個鏈路處理的handler
        //setNextHandler(new Dean());
    }
}
public class Dean extends Handler {
    public Dean() {
        //院長處理3-7天的請假
        super(Handler.NUM_THREE, Handler.NUM_SEVEN);
    }
    @Override
    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("院長審批:同意。");
        //也可以在這裡設定下一個鏈路處理的handler
        //setNextHandler(new CollegeSecretary ());
    }
}
public class CollegeSecretary extends Handler {
    public CollegeSecretary() {
        //學院書記處理7天以上的請假
        super(Handler.NUM_SEVEN);
    }
    @Override
    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("學院書記審批:同意。");
        //也可以在這裡設定下一個鏈路處理的handler
        //setNextHandler(null); //最後一個
    }
}

測試類

public class TestClient {
    public static void main(String[] args) {
        //請假條來一張
        LeaveRequest leave = new LeaveRequest("kaico",8,"身體不適");
        //各級領導
        Counselor counselor= new Counselor();
        //如果前面handleLeave 方法中設定了下一個handler,這裡就不需要了,直接提交申請就好了
        Dean dean = new Dean();
        CollegeSecretary collegeSecretary = new CollegeSecretary();
        counselor.setNextHandler(dean);//輔導員的領導是院長
        dean.setNextHandler(collegeSecretary);//院長的領導是學院書記
        //提交申請
        counselor.submit(leave);
    }
}

到此這篇關於Java設計模式之責任鏈模式詳解的文章就介紹到這了,更多相關Java責任鏈模式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com