設計模式之職責鏈模式


定義:使多個對象都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有對象處理它為止。

類型:行為類模式

類圖:

責任連模式的結構

        責任連模式的類圖非常簡單,它由一個抽象地處理類和它的一組實現類組成:

  • 抽象處理類:抽象處理類中主要包含一個指向下一處理類的成員變量nextHandler和一個處理請求的方法handRequest,handRequest方法的主要主要思想是,如果滿足處理的條件,則有本處理類來進行處理,否則由nextHandler來處理。
  • 具體處理類:具體處理類主要是對具體的處理邏輯和處理的適用條件進行實現。

適用場景:

1、有多個的對象可以處理一個請求,哪個對象處理該請求運行時刻自動確定;

2、在不明確指定接收者的情況下,向多個對象中的一個提交一個請求;

3、處理一個請求的對象集合應被動態指定。

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

 

       職責鏈模式的主要優點在於可以降低系統的耦合度,簡化對象的相互連接,同時增強給對象指派職責的靈活性,增加新的請求處理類也很方便;其主要缺點在於不能保證請求一定被接收,且對於比較長的職責鏈,請求的處理可能涉及到多個處理對象,系統性能將受到一定影響,而且在進行代碼調試時不太方便。
 

在大學里面當班干部,時常要向上級申請各方面的東西。譬如申請全班外出秋游,普通同學將申請表交給班長,班長簽字之后交給輔導員,輔導員批准之后上交到主任辦公室…就是這樣,一個請求(這里是一份申請表)有時候需要經過好幾個級別的處理者(這里是輔導員、主任)的審查才能夠最終被確定可行與否。

在這里表現出來的是一個職責鏈,即不同的處理者對同一個請求可能擔負着不同的處理方式、權限,但是我們希望這個請求必須到達最終拍板的處理者(否則秋游就沒戲了)。這種關系就很適合使用職責鏈模式了。

類圖結構如下:

 代碼實現如下:

  1. // 全局變量,接口類型  
  2. /**  
  3.  * 使用Java中的interface定義全局變量,可根據具體需要在   
  4.  * 具體的包中使用靜態導入相關的全局變量,語法如下:   
  5.  *  import static package01.package02.*;  
  6.  */ 
  7. interface Levels {  
  8.     public static final int LEVEL_01 = 1;  
  9.     public static final int LEVEL_02 = 2;  
  10.     public static final int LEVEL_03 = 3;  

 

  1. // 抽象請求類  
  2. abstract class AbstractRequest {  
  3.     private String content = null;  
  4.  
  5.     public AbstractRequest(String content) {  
  6.         this.content = content;  
  7.     }  
  8.  
  9.     public String getContent() {  
  10.         return this.content;  
  11.     }  
  12.  
  13.     // 獲得請求的級別  
  14.     public abstract int getRequestLevel();  

 

  1. // 具體請求類01  
  2. class Request01 extends AbstractRequest {  
  3.     public Request01(String content) {  
  4.         super(content);  
  5.     }  
  6.  
  7.     @Override 
  8.     public int getRequestLevel() {  
  9.         return Levels.LEVEL_01;  
  10.     }  
  11. }  
  12.  
  13. // 具體請求類02  
  14. class Request02 extends AbstractRequest {  
  15.     public Request02(String content) {  
  16.         super(content);  
  17.     }  
  18.  
  19.     @Override 
  20.     public int getRequestLevel() {  
  21.         return Levels.LEVEL_02;  
  22.     }  
  23. }  
  24.  
  25. // 具體請求類03  
  26. class Request03 extends AbstractRequest {  
  27.     public Request03(String content) {  
  28.         super(content);  
  29.     }  
  30.  
  31.     @Override 
  32.     public int getRequestLevel() {  
  33.         return Levels.LEVEL_03;  
  34.     }  

 

  1. // 抽象處理者類,  
  2. abstract class AbstractHandler {  
  3.     // 責任鏈的下一個節點,即處理者  
  4.     private AbstractHandler nextHandler = null;  
  5.  
  6.     // 捕獲具體請求並進行處理,或是將請求傳遞到責任鏈的下一級別  
  7.     public final void handleRequest(AbstractRequest request) {  
  8.  
  9.         // 若該請求與當前處理者的級別層次相對應,則由自己進行處理  
  10.         if (this.getHandlerLevel() == request.getRequestLevel()) {  
  11.             this.handle(request);  
  12.         } else {  
  13.             // 當前處理者不能勝任,則傳遞至職責鏈的下一節點  
  14.             if (this.nextHandler != null) {  
  15.                 System.out.println("當前 處理者-0" + this.getHandlerLevel()  
  16.                         + " 不足以處理 請求-0" + request.getRequestLevel());  
  17.                   
  18.                 // 這里使用了遞歸調用  
  19.                 this.nextHandler.handleRequest(request);  
  20.             } else {  
  21.                 System.out.println("職責鏈上的所有處理者都不能勝任該請求...");  
  22.             }  
  23.         }  
  24.     }  
  25.  
  26.     // 設置責任鏈中的下一個處理者  
  27.     public void setNextHandler(AbstractHandler nextHandler) {  
  28.         this.nextHandler = nextHandler;  
  29.     }  
  30.  
  31.     // 獲取當前處理者的級別  
  32.     protected abstract int getHandlerLevel();  
  33.  
  34.     // 定義鏈中每個處理者具體的處理方式  
  35.     protected abstract void handle(AbstractRequest request);  

 

  1. // 具體處理者-01  
  2. class Handler01 extends AbstractHandler {  
  3.     @Override 
  4.     protected int getHandlerLevel() {  
  5.         return Levels.LEVEL_01;  
  6.     }  
  7.  
  8.     @Override 
  9.     protected void handle(AbstractRequest request) {  
  10.         System.out.println("處理者-01 處理 " + request.getContent() + "\n");  
  11.     }  
  12. }  
  13.  
  14. // 具體處理者-02  
  15. class Handler02 extends AbstractHandler {  
  16.     @Override 
  17.     protected int getHandlerLevel() {  
  18.         return Levels.LEVEL_02;  
  19.     }  
  20.  
  21.     @Override 
  22.     protected void handle(AbstractRequest request) {  
  23.         System.out.println("處理者-02 處理 " + request.getContent()+ "\n");  
  24.     }  
  25. }  
  26.  
  27. // 具體處理者-03  
  28. class Handler03 extends AbstractHandler {  
  29.     @Override 
  30.     protected int getHandlerLevel() {  
  31.         return Levels.LEVEL_03;  
  32.     }  
  33.  
  34.     @Override 
  35.     protected void handle(AbstractRequest request) {  
  36.         System.out.println("處理者-03 處理 " + request.getContent()+ "\n");  
  37.     }  

 

  1. // 測試類  
  2. public class Client {  
  3.     public static void main(String[] args) {  
  4.         // 創建指責鏈的所有節點  
  5.         AbstractHandler handler01 = new Handler01();  
  6.         AbstractHandler handler02 = new Handler02();  
  7.         AbstractHandler handler03 = new Handler03();  
  8.  
  9.         // 進行鏈的組裝,即頭尾相連,一層套一層  
  10.         handler01.setNextHandler(handler02);  
  11.         handler02.setNextHandler(handler03);  
  12.  
  13.         // 創建請求並提交到指責鏈中進行處理  
  14.         AbstractRequest request01 = new Request01("請求-01");  
  15.         AbstractRequest request02 = new Request02("請求-02");  
  16.         AbstractRequest request03 = new Request03("請求-03");  
  17.           
  18.         // 每次提交都是從鏈頭開始遍歷  
  19.         handler01.handleRequest(request01);  
  20.         handler01.handleRequest(request02);  
  21.         handler01.handleRequest(request03);  
  22.     }  

測試結果:

  1. 處理者-01 處理 請求-01 
  2.  
  3. 當前 處理者-01 不足以處理 請求-02 
  4. 處理者-02 處理 請求-02 
  5.  
  6. 當前 處理者-01 不足以處理 請求-03 
  7. 當前 處理者-02 不足以處理 請求-03 
  8. 處理者-03 處理 請求-03 
在上面抽象處理者 AbstractHandler 類的 handleRequest() 方法中,被 protected 修飾,並且該方法中調用了兩個必須被子類覆蓋實現的抽象方法,這里是使用了模板方法模式(Template Mehtod)。其實在這里,抽象父類的 handleRequest() 具備了請求傳遞的功能,即對某些請求不能處理時,馬上提交到下一結點(處理者)中,而每個具體的處理者僅僅完成了具體的處理邏輯,其他的都不用理。
 
記得第一次看到職責鏈模式的時候,我很驚訝於它能夠把我們平時在代碼中的 if..else.. 的語句塊變成這樣靈活、適應變化。例如:如果現在輔導員請長假了,但我們的秋游還是要爭取申請成功呀,那么我們在 Client 類中可以不要創建 handler02,即不要將該處理者組裝到職責鏈中。這樣子處理比 if..else..好多了。或者說,突然來了個愛管閑事的領導,那么我照樣可以將其組裝到職責鏈中。
 
關於上面使用場景中提到的3個點:
1、處理者在運行時動態確定其實是我們在 Client 中組裝的鏈所引起的,因為具體的職責邏輯就在鏈中一一對應起來;
2、因為不確定請求的具體處理者是誰,所以我們把所有可能的處理者組裝成一條鏈,在遍歷的過程中就相當於向每個處理者都提交了這個請求,等待其審查。並且在審查過程中,即使不是最終處理者,也可以進行一些請求的“包裝”操作(這種功能類似於裝飾者模式),例如上面例子中的簽名批准;
3、處理者集合的動態指定跟上面的第1、2點類似,即在 Client 類中創建了所有可能的處理者。
 
不足之處:

1、對於每一個請求都需要遍歷職責鏈,性能是個問題;

2、抽象處理者 AbstractHandler 類中的 handleRequest() 方法中使用了遞歸,棧空間的大小也是個問題。

 

參考:http://blog.csdn.net/zhengzhb/article/details/7568676

http://haolloyin.blog.51cto.com/1177454/342166/

http://blog.csdn.net/qq7342272/article/details/6921524

http://blog.csdn.net/hguisu/article/details/7547231

http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html

http://www.cnblogs.com/xudong-bupt/p/3617860.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM