首頁 Java java教程 實例講解Java的設計模式程式設計中責任鏈模式的運用

實例講解Java的設計模式程式設計中責任鏈模式的運用

Jan 19, 2017 pm 05:04 PM

定義:使多個物件都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。
類型:行為類別模式
類別圖:

實例講解Java的設計模式程式設計中責任鏈模式的運用

首先來看一段程式碼:

public void test(int i, Request request){
  if(i==1){
    Handler1.response(request);
  }else if(i == 2){
    Handler2.response(request);
  }else if(i == 3){
    Handler3.response(request);
  }else if(i == 4){
    Handler4.response(request);
  }else{
    Handler5.response(request);
  }
}
登入後複製

    i  程式碼的商業邏輯是這樣的,方法有兩個參數要求:整數和一個值來決定由誰來處理request,如果i==1,由Handler1來處理,如果i==2,由Handler2來處理,以此類推。在程式設計中,這種處理業務的方法非常常見,所有處理請求的類別都有if…else…條件判斷語句連成一條責任鏈來對請求進行處理,相信大家都常用到。這種方法的優點是非常直觀,簡單明了,而且比較容易維護,但是這種方法也存在著幾個比較令人頭疼的問題:
程式碼臃腫:實際應用中的判定條件通常不是這麼簡單地判斷是否為1或是否為2,也許需要複雜的計算,也許需要查詢資料庫等等,這就會有很多額外的程式碼,如果判斷條件再比較多,那麼這個if…else…語句基本上就沒辦法看了。
耦合度高:如果我們想繼續加入處理請求的類,那麼就要繼續加入else if判定條件;另外,這個條件判定的順序也是寫死的,如果想改變順序,那麼也只能修改這個條件語句。
        因缺點我們已經清楚了,就要想辦法解決。這個場景的業務邏輯很簡單:如果滿足條件1,則由Handler1來處理,不滿足則向下傳遞;如果滿足條件2,則由Handler2來處理,不滿足則繼續向下傳遞,以此類推,直到條件結束。其實改進的方法也很簡單,就是把判定條件的部分放到處理類別中,這就是責任連模式的原理。
 
責任連模式的結構
        責任連模式的類別圖非常簡單,它由一個抽像地處理類別和它的一組實作類別組成:
抽象處理類別:抽象處理類別中主要包含一個指向下一類別的成員變數nextHandler和一個處理請求的方法handRequest,handRequest方法的主要主要想法是,如果滿足處理的條件,則有本處理類別來進行處理,否則由nextHandler來處理。
具體處理類別:具體處理類別主要是對具體的處理邏輯和處理的適用條件進行實作。
 實例

責任鏈模式有兩個角色:
抽象處理者(Handler)角色 :定義一個請求的介面。如果需要可以定義個一個方法用來設定和傳回下家物件的參考。
具體處理者(ConcreteHandler)角色 :如果可以處理就處理請求,如果不能處理,就把請求傳給下家,讓下家處理。也就是說它處理自己能處理的請求且可以存取它的下家。
上述模式的測試代碼如下:

package chainOfResp;
/**
 *描述:抽象处理角色
 */
public abstract class Handler {
 
 protected Handler successor;
 /**
  *描述:处理方法
  */
 public abstract void handlerRequest(String condition);
  
  
 public Handler getSuccessor() {
  return successor;
 }
 public void setSuccessor(Handler successor) {
  this.successor = successor;
 }
  
}
登入後複製
package chainOfResp;
/**
 *描述:具体处理角色
 */
public class ConcreteHandler1 extends Handler {
 
 @Override
 public void handlerRequest(String condition) {
  // 如果是自己的责任,就自己处理,负责传给下家处理
  if(condition.equals("ConcreteHandler1")){
   System.out.println( "ConcreteHandler1 handled ");
   return ;
  }else{
   System.out.println( "ConcreteHandler1 passed ");
   getSuccessor().handlerRequest(condition);
  }
 }
 
}
登入後複製
package chainOfResp;
/**
 *描述:具体处理角色
 */
public class ConcreteHandler2 extends Handler {
  
 @Override
 public void handlerRequest(String condition) {
  // 如果是自己的责任,就自己处理,负责传给下家处理
  if(condition.equals("ConcreteHandler2")){
   System.out.println( "ConcreteHandler2 handled ");
   return ;
  }else{
   System.out.println( "ConcreteHandler2 passed ");
   getSuccessor().handlerRequest(condition);
  }
 }
 
}
登入後複製
package chainOfResp;
/**
 *描述:具体处理角色
 */
public class ConcreteHandlerN extends Handler {
 
 /**
  * 这里假设n是链的最后一个节点必须处理掉
  * 在实际情况下,可能出现环,或者是树形,
  * 这里并不一定是最后一个节点。
  *
  */
 @Override
 public void handlerRequest(String condition) {
 
  System.out.println( "ConcreteHandlerN handled");
   
 }
 
}
登入後複製

  

package chainOfResp;
/**
 *描述:测试类
 */
public class Client {
 
 /**
  *描述:
  */
 public static void main(String[] args) {
  
  Handler handler1 = new ConcreteHandler1();
  Handler handler2 = new ConcreteHandler2();
  Handler handlern = new ConcreteHandlerN();
   
  //链起来
  handler1.setSuccessor(handler2);
  handler2.setSuccessor(handlern);
   
  //假设这个请求是ConcreteHandler2的责任
  handler1.handlerRequest("ConcreteHandler2");
   
   
 }
 
}
登入後複製

舉這樣一個例子,在玩具工廠的生產車間,流水線就是一條責任鏈,假如一個玩具飛機有外殼裝配員,引擎裝配員,螺旋槳裝配員,模型包裝員組成。當這個物件飛機流到誰那裡,誰就負責安裝他負責的這一部分,這部分安裝完成後流到下一個環節,知道所有環境完成。這個是一生成的責任鏈。還有一個品質檢測鏈,品質檢測也分多部,外殼檢測,引擎檢測,螺旋槳檢測,包裝檢測。當產品留到檢測員那裡檢測自己負責的那一塊,如果有問題直接拎出來,如果沒問題則傳給下一個檢測員,直到所有檢測完成。這兩個都是責任鏈,但是差異是,產生責任鏈每個人都會處理,並處理一部分;而品質偵測責任鏈經過判斷,要麼處理掉,要麼不處理流下去。這就是責任鏈的兩種分類,後一種叫做純的責任鏈,前一種叫做不純的責任鏈,純的責任鏈在實際應用中很少存在,常見的為不純的責任鏈,上面的模型是模擬純的責任鏈來處理的。
 

責任鏈模式的優缺點
        責任鏈模式與if…else…相比,他的耦合性較低一些,因為它將條件判定分散到了各個處理類別中,而這些處理類別的優先處理順序可以隨意設定。責任鏈模式也有缺點,這與if…else…語句的缺點是一樣的,那就是在找到正確的處理類別之前,所有的判定條件都要被執行一遍,當責任鏈比較長時,性能問題比較嚴重。
 
責任鏈模式的適用場景
       就像開始的例子那樣,假如使用if…else…語句來組織一個責任鏈時感到力不從心,代碼看起來很糟糕時,就可以使用責任鏈模式來進行重構。
 
總結
       責任鏈模式其實就是一個彈性版的if…else…語句,它就是將這些判定條件的語句放到了各個處理類別中,這樣做的優點是比較靈活了,但同樣也帶來了風險,例如設定處理類別前後關係時,一定要特別仔細,搞對處理類別前後邏輯的條件判斷關係,並且注意不要在鏈中出現循環引用的問題。

更多實例講解Java的設計模式編程中責任鏈模式的運用相關文章請關注PHP中文網!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? 使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名構建查詢條件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...

See all articles