軟件設計模式學習(十七)職責鏈模式


系統中若是存在多個對象能夠處理一個同一請求,能夠經過職責鏈模式將這些處理請求的對象連成一條鏈,讓請求沿着該鏈進行傳遞。若是鏈上的對象能夠處理該請求則進行處理,不然將請求轉發給下家處理html


模式動機

不少狀況下,能夠處理某個請求的對象不止一個,如大學裏的獎學金審批,學生先向輔導員提交審批表,輔導員簽字審批後再交給系主任簽字審批,接着是院長審批,最後多是校長審批,在這個過程當中,獎學金申請表能夠看做一個請求對象,不一樣級別審批者均可以處理該請求,除了輔導員以外,學生不需一一和其餘審批者交互,只需等待結果便可。審批過程當中若是某一審批者認爲不符合條件,則請求停止,不然將請求傳遞給下一審批者,最後由校長拍板。java

在這個過程當中,輔導員、系主任、院長、校長構成一條鏈,申請表沿着這條鏈傳遞,就叫職責鏈。職責鏈能夠是一條直線、一個環或一個樹形結構,常見的職責鏈是直線型。請求沿着鏈傳遞,由鏈上的處理者對請求進行處理,客戶無須關心請求的處理和傳遞細節,實現請求發送者和請求處理者解耦。設計模式


模式定義

避免請求者與接收者耦合在一塊兒,讓多個對象都有可能接受請求,將這些對象鏈接成一條鏈,而且沿着這條鏈傳遞請求,直到有對象處理爲止。職責鏈模式也叫責任鏈模式,它是一種對象行爲型模式。ide


模式結構

  1. Handler(抽象處理者)性能

    定義了一個處理請求的接口,因爲不一樣的具體處理者處理請求方式不一樣,所以在其中定義抽象請求處理方法。在抽象處理者中定義一個自類型(抽象處理者類型)的對象,做爲對下家的引用。學習

  2. ConcreteHandler(具體處理者)測試

    具體處理者是抽象處理者子類,實現抽象請求處理方法,處理用戶請求。在處理請求以前要進行判斷,看是否具備相應處理權限,若是能夠處理就處理,不然將請求轉發給後繼者。this

  3. Client(客戶類)設計

    用於向鏈中對象提出最初的請求,客戶類只關心鏈的源頭,而無須關心請求的處理細節和傳遞過程。代理


模式實例

某系統提供一個假條審批的模塊,若是員工請假天數小於 3 天,主任能夠審批該假條;若是員工請假天數大於等於 3 天,小於 10 天,經理能夠審批;若是員工請假天數大於等於 10 天,小於 30 天,總經理能夠審批;若是超過 30 天,總經理也不能審批,提示相應的拒絕信息。

  1. 請求類 LeaveRequest(請假條類)

    //	封裝請求的相關信息,以便處理者對其進行處理
    public class LeaveRequest {
    
        private String leaveName;
        private int leaveDays;
    
        public LeaveRequest(String leaveName, int leaveDays) {
            this.leaveName = leaveName;
            this.leaveDays = leaveDays;
        }
    
        public void setLeaveName(String leaveName) {
            this.leaveName = leaveName;
        }
    
        public void setLeaveDays(int leaveDays) {
            this.leaveDays = leaveDays;
        }
    
        public String getLeaveName() {
            return leaveName;
        }
    
        public int getLeaveDays() {
            return leaveDays;
        }
    }
  2. 抽象處理類 Leader(領導類)

    public abstract class Leader {
    
        protected String name;
        protected Leader successor;	//	做爲對下家的引用
    
        public Leader(String name) {
            this.name = name;
        }
    
        public void setSuccessor(Leader successor) {
            this.successor = successor;
        }
    
        public abstract void handleRequest(LeaveRequest request);
    }
  3. 具體處理者 Director(主任類)

    public class Director extends Leader {
    
        public Director(String name) {
            super(name);
        }
    
        @Override
        public void handleRequest(LeaveRequest request) {
            if (request.getLeaveDays() < 3) {
                System.out.println("主任" + name + "審批員工" + request.getLeaveName() +
                        "的請假條,請假天數爲" + request.getLeaveDays() + "天");
            } else {
                if (this.successor != null) {
                    this.successor.handleRequest(request);
                }
            }
        }
    }
  4. 具體處理者 Manager(經理類)

    public class Manager extends Leader {
    
        public Manager(String name) {
            super(name);
        }
    
        @Override
        public void handleRequest(LeaveRequest request) {
            if (request.getLeaveDays() < 10) {
                System.out.println("經理" + name + "審批員工" + request.getLeaveName() +
                        "的請假條,請假天數爲" + request.getLeaveDays() + "天");
            } else {
                if (this.successor != null) {
                    this.successor.handleRequest(request);
                }
            }
        }
    }
  5. 具體處理者 GeneralManager(總經理類)

    public class GeneralManager extends Leader {
    
        public GeneralManager(String name) {
            super(name);
        }
    
        @Override
        public void handleRequest(LeaveRequest request) {
            if (request.getLeaveDays() < 30) {
                System.out.println("總經理" + name + "審批員工" + request.getLeaveName() +
                        "的請假條,請假天數爲" + request.getLeaveDays() + "天");
            } else {
                System.out.println("想請假" + request.getLeaveDays() + "天?你是不想幹了吧!");
            }
        }
    }
  6. 客戶端測試類 Client

    public class Client {
    
        public static void main(String[] args) {
    
            Leader director = new Director("王明");
            Leader manager = new Manager("趙強");
            Leader generalManager = new GeneralManager("陳勇");
    
            director.setSuccessor(manager);
            manager.setSuccessor(generalManager);
    
            LeaveRequest lr1 = new LeaveRequest("張三", 2);
            director.handleRequest(lr1);
    
            LeaveRequest lr2 = new LeaveRequest("李四", 5);
            director.handleRequest(lr2);
    
            LeaveRequest lr3 = new LeaveRequest("王五", 15);
            director.handleRequest(lr3);
    
            LeaveRequest lr4 = new LeaveRequest("趙六", 45);
            director.handleRequest(lr4);
        }
    }
  7. 運行結果


模式優缺點

職責鏈模式優勢以下:

  1. 下降耦合度。對象不需知道是誰處理請求,之需等待處理結果便可。接收者和發送則都沒有對方的明確信息,且鏈中的對象不須要知道鏈的結構,由客戶端負責鏈的建立
  2. 簡化對象的相互鏈接。請求處理對象僅需維持一個指向其後繼者的引用,而不需維持對全部候選處理者的引用
  3. 加強給對象指派職責的靈活性。能夠經過在運行時對該鏈進行動態的增長或修改來增長或改變一個請求
  4. 增長新的請求處理類很方便。增長一個新的具體請求處理者無須修改源代碼,只需在客戶端從新建鏈便可,符合開閉原則

職責鏈模式缺點以下:

  1. 不能保證請求必定被接收。該請求可能一直到末端都得不處處理,也有可能沒有被正確配置而得不處處理
  2. 對於較長的職責鏈,請求的處理可能涉及多個處理對象,系統性能將受到必定影響,進行代碼調式也不方便

模式適用環境

如下狀況能夠考慮使用職責鏈模式:

  1. 有多個對象能夠處理同一請求,具體哪一個對象處理由運行時刻決定
  2. 在不明確指定接收者的狀況下,向多個對象中的一個提交請求。請求沿着鏈進行傳遞,尋找相應的處理者
  3. 動態指定一組對象處理請求,客戶端能夠動態建立職責鏈來處理請求,還能夠動態改變鏈中處理者之間的前後次序

純與不純的職責鏈模式

一個純的職責鏈模式要求某一處理者對象要麼接收請求,承擔責任,要麼把責任推給下家。在一個不純的職責鏈模式裏面,一個請求能夠被由某一處理對象承擔一部分責任後,又將責任往下傳,或者最終不被任何接收端對象所接收。實際中咱們接觸到的大可能是不純的職責鏈模式。


上一站:軟件設計模式學習(十六)代理模式
下一站:軟件設計模式學習(十八)命令模式

相關文章
相關標籤/搜索