不少狀況下,一個軟件系統中能夠處理某個請求的對象不知一個,好比採購單的審批,主任,副董事長,董事長,董事會均可以處理採購單,他們能夠構成一條處理採購單的鏈式結構,採購單沿着這條鏈進行傳遞,這條鏈就叫職責鏈。java
職責鏈能夠是一條直線,一個環或者一個樹形結構,最多見的職責鏈是直線型,即沿着一條單向的鏈來傳遞請求。鏈上的每個對象都是請求處理者,職責鏈模式能夠將請求的處理者組織成一條鏈,並讓請求沿着鏈傳遞,由鏈上的處理者對請求進行處理,客戶端無須關係請求的處理細節以及具體的傳遞,只須要將請求發送到鏈上便可,實現請求發送者以及請求處理者的解耦。編程
職責鏈模式:避免將請求發送者與接收者耦合在一塊兒,讓多個對象都有機會接收請求,將這些對象鏈接成一條鏈,而且沿着這條鏈傳遞請求,直到有對象處理它爲止。微信
職責鏈模式是一種行爲型模式。dom
Handler
(抽象處理者):定義一個處理請求的接口,通常爲抽象類。由於每個處理者的下家仍是一個處理者,所以在抽象處理者中定義了一個抽象處理者的對象做爲對下一個處理者的引用,經過該引用,處理者能夠連成一條鏈ConcreteHandler
(具體處理者):抽象處理者的子類,實現具體處理方法,在處理前須要判斷是否具備處理權限,若是擁有權限則處理,沒有則轉發到下一個處理者protected
abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void handleRequest(int num); }
擁有一個設置下一處理者的對象,能夠經過setter注入,同時聲明抽象處理方法。ide
class ConcreteHandler1 extends Handler { @Override public void handleRequest(int num) { if(num < 10) { System.out.println("處理小於10的數字:"+num); } else successor.handleRequest(num); } } class ConcreteHandler2 extends Handler { @Override public void handleRequest(int num) { if(num < 20) { System.out.println("處理大於等於10且小於20的數字:"+num); } else successor.handleRequest(num); } } class ConcreteHandler3 extends Handler { @Override public void handleRequest(int num) { if(num < 30) { System.out.println("處理大於等於20且小於30的數字:"+num); } else successor.handleRequest(num); } }
繼承抽象處理者,首先判斷是否擁有權限處理(這裏是一個簡單的if判斷),若是有就處理,沒有的話經過protected
對象,也就是轉發給下一個處理者處理。性能
public static void main(String[] args) { Handler handler = new ConcreteHandler1(); Handler handler2 = new ConcreteHandler2(); Handler handler3 = new ConcreteHandler3(); handler.setSuccessor(handler2); handler2.setSuccessor(handler3); handler.handleRequest(3); handler.handleRequest(15); handler.handleRequest(22); }
客戶端針對抽象處理者編程,須要建立每個具體處理者對象,而且自定義職責鏈:測試
handler.setSuccessor(handler2); handler2.setSuccessor(handler3);
接着調用對應的處理者處理便可。this
設計一個採購單審批系統,分級進行,根據金額不一樣由不一樣層次的人員審批,主任能夠審批5w如下的採購單,副董事長能夠審批5w-10w,董事長能夠審批10w-50w,50w以上須要由董事會審批,使用職責鏈模式設計該系統。
設計以下:spa
Approver
Director
+VicePresident
+President
+Congress
PurchaseRequest
代碼以下:設計
//抽象處理者 abstract class Approver { protected Approver successor; public void setSuccessor(Approver successor) { this.successor = successor; } public abstract void processRequest(PurchaseRequest request); } //具體處理者:主任 class Director extends Approver { @Override public void processRequest(PurchaseRequest request) { if(request.getAmount() < 50000) System.out.println("主任審批一筆\n金額爲"+request.getAmount()+"\nid爲"+request.getId()+"\n的採購單\n"); else successor.processRequest(request); } } //具體處理者:副董事長 class VicePresident extends Approver { @Override public void processRequest(PurchaseRequest request) { if(request.getAmount() < 100000) System.out.println("副董事長審批一筆\n金額爲"+request.getAmount()+"\nid爲"+request.getId()+"\n的採購單\n"); else successor.processRequest(request); } } //具體處理者:董事長 class President extends Approver { @Override public void processRequest(PurchaseRequest request) { if(request.getAmount() < 500000) System.out.println("董事長審批一筆\n金額爲"+request.getAmount()+"\nid爲"+request.getId()+"\n的採購單\n"); else successor.processRequest(request); } } //具體處理者:董事會 class Congress extends Approver { @Override public void processRequest(PurchaseRequest request) { System.out.println("董事會審批一筆\n金額爲"+request.getAmount()+"\nid爲"+request.getId()+"\n的採購單\n"); } } //請求類:採購單 class PurchaseRequest { private double amount; private String id; private static final String STR = "xcnvj232cvm"; private static final Random random = new Random(); public PurchaseRequest(double amount) { this.amount = amount; //簡易的隨機字符串 this.id = STR.substring(0,random.nextInt(STR.length()-1)+1).repeat(random.nextInt(3)+2); } public double getAmount() { return this.amount; } public void setAmount(double amount) { this.amount = amount; } public String getId() { return this.id; } public void setId(String id) { this.id = id; } }
測試:
public static void main(String[] args) { Approver director = new Director(); Approver vicePresident = new VicePresident(); Approver president = new President(); Approver congress = new Congress(); director.setSuccessor(vicePresident); vicePresident.setSuccessor(president); president.setSuccessor(congress); director.processRequest(new PurchaseRequest(12345)); director.processRequest(new PurchaseRequest(54321)); director.processRequest(new PurchaseRequest(123456)); director.processRequest(new PurchaseRequest(654321)); }
輸出以下:
職責鏈模式能夠分爲純的職責鏈模式與不純的職責鏈模式。
一個純的職責鏈模式要求一個具體處理者對象只能在兩個行爲中選擇一個,要麼承擔所有責任,要麼將責任推給下家,不容許出現某一個具體處理者對象在承擔了一部分或所有責任後又將責任向下傳遞的狀況。
並且在純的職責鏈模式中,要求一個請求必須被某一個處理者對象接收,不能出現某個請求未被任何一個處理者對象處理的狀況,好比前面的採購單例子。
在一個不純的職責鏈模式中,容許某個請求被一個具體處理者部分處理後再向下傳遞,或者一個具體處理者處理完某請求後其猴戲處理者能夠繼續處理該請求,並且一個請求能夠最終不被任何處理者對象所接收。
在Java AWT 1.0中的事件處理模型應用就是不純的職責鏈模式,基本原理以下:因爲窗口組件通常位於容器組件中,當事件發生在窗口組件上時,先經過組件對象的handleEvent()
方法傳遞給相應的事件處理方法,該事件處理方法將處理該事件,而後決定是否將該事件向上一級容器組件傳播,上級容器組件在接到事件以後能夠繼續處理此事件並決定是否繼續向上級容器組件傳播,直到頂層容器組件爲止。若是一直都沒有處理方法則不處理該事件。
這種事件處理機制又叫事件浮升機制,JDK1.1後使用觀察者模式來代理職責鏈模式處理事件。
若是以爲文章好看,歡迎點贊。
同時歡迎關注微信公衆號:氷泠之路。