java設計模式解析(11) Chain責任鏈模式


 

設計模式系列文章



java設計模式解析(1) Observer觀察者模式
java設計模式解析(2) Proxy代理模式
java設計模式解析(3) Factory工廠模式
java設計模式解析(4) Singleton單例模式
java設計模式解析(5) Delegate委派模式
java設計模式解析(6) Strategy策略模式
java設計模式解析(7) Prototype原型模式
java設計模式解析(8) Template模版模式
java設計模式解析(9) Decorator裝飾模式
java設計模式解析(10) Adapter適配模式
java設計模式解析(11) Chain責任鏈模式
 

 

 

 

 

 

 

 

  

 

 主要內容

 

 

1、簡述

2、實現代碼(Talk is cheap,Show me the code)

3、注意點

 

1、簡述

Chain責任鏈模式在《設計模式之禪》定義: 使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關系。將這些對象連成一條線,並沿着這條鏈傳遞該請求,直至有對象處理它為止。

 責任鏈的核心在“鏈”,由“鏈”上所有的成員去處理請求並返回結果。 類圖中各個角色定義如下:

  • Client:客戶端向發起請求,責任鏈對客戶端透明
  • Handler:責任鏈抽象類,負責定義處理邏輯以及組裝責任鏈機制
  • ConcreteHandler:責任鏈中的鏈由多個ConcreteHandler組裝而成

 

 結合上述給偽碼:

==> Handler類

 1 public abstract class Handler {
 2     private Handler nextHandler ;
 3 
 4     public final Response handlerMessage(Request request){
 5         Response response = null ;
 6         // 符合自己處理
 7         if(this.getHandlerLevel().equals(request.getRequestLevel())){
 8             response = this.echo(request) ;
 9         }
10         // 交由其他人處理
11         else if (nextHandler != null) {
12             response = nextHandler.handlerMessage(request) ;
13         }
14         return response ;
15     }
16 
17     // 組裝責任鏈
18     public void setNextHandler(Handler nextHandler) {
19         this.nextHandler = nextHandler;
20     }
21 
22     // 模版方法 由具體的責任鏈實現者定義
23     protected abstract Level getHandlerLevel();
24     protected abstract Response echo(Request request);
25 }

 ==> ConcreteHandler1、ConcreteHandler2、ConcreteHandler3三個類代碼類似,都是實際責任鏈一員且通過繼承Handler只需要實現自己的邏輯部分。

 1 public class ConcreteHandler1 extends Handler {
 2     @Override
 3     protected Level getHandlerLevel() {
 4         return null;
 5     }
 6 
 7     @Override
 8     protected Response echo(Request request) {
 9         return null;
10     }
11 }

 ==> Client客戶端發起請求 此時包含了責任鏈的組裝和調用 實際可以增加代理簡化Client操作

 1 public class Client {
 2     public static void main(String[] args) {
 3 
 4         // 組裝責任鏈
 5         ConcreteHandler1 handler1 = new ConcreteHandler1() ;
 6         ConcreteHandler2 handler2 = new ConcreteHandler2() ;
 7         ConcreteHandler3 handler3 = new ConcreteHandler3() ;
 8         handler1.setNextHandler(handler2);
 9         handler2.setNextHandler(handler3);
10 
11         // 發起調用
12         Response response = handler1.handlerMessage(new Request()) ;
13     }

 以上偽碼顯示責任鏈模式基本代碼實現,然后實際會依據情況有很多變化。如每個鏈條只處理部分數據並交由后鏈條執行,直至責任鏈的終止,甚至可以沒有任何返回結果,接下來小節將展示一個自動組裝的責任鏈demo。

 2、實現代碼(Talk is cheap,Show me the code)

 根據責任鏈模式設計細想,在服務提供的前置增加一個責任鏈,以完成參數校驗、簽名、日志、監控、追蹤等通用的任務。對於客戶端完全透明,對於服務端利用JAVA SPI機制(DUBBO SPI思想)靈活組裝配置責任鏈,而如果結合上強大的spring Bean容器,很容易完成服務框架的定制工作。

下面demo示例:

  • Chain: 基本責任鏈中的鏈條定義 
  • ChainHandler:負責責任鏈的組裝和調用邏輯
  • ChainLoader:利用JAVA SPI機制,加載具體責任鏈實現
1 public interface Process<T> {
2     T doProcess() ;
3 }
Process.java
 1 package com.nancy.chain.auto;
 2 
 3 
 4 public interface Chain {
 5     int HIGHEST_ORDER = Integer.MIN_VALUE ;
 6     int LOWEREST_ORDER = Integer.MAX_VALUE  ;
 7 
 8     /**
 9      * 處理邏輯
10      * @param chainHandler 責任鏈組裝
11      * @param pos 下一個觸發下標
12      * @param process 實際處理邏輯
13      * @return T 返回結果
14      */
15     <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) ;
16 
17     /**
18      * 配置等級 越高優先級(越小) 越優先觸發
19      * @param
20      * @return
21      */
22     default Integer getOrder() {
23         return HIGHEST_ORDER ;
24     }
25 
26 }
Chain.java
1 public abstract class AbstractChain implements Chain, Cloneable {
2 
3 }
AbstractChain.java
 1 public class ChainHandler extends AbstractChain {
 2 
 3     private List<Chain> chains ;
 4 
 5     public ChainHandler(List<Chain> chains){
 6         this.chains = chains ;
 7         chains.sort(Comparator.comparingInt(Chain::getOrder));
 8     }
 9 
10     private boolean hasNext(int pos){
11         return chains.size()-1 >= pos ;
12     }
13 
14     public List<Chain> getChains() {
15         return chains;
16     }
17 
18     public void setChains(List<Chain> chains) {
19         this.chains = chains;
20     }
21 
22     @Override
23     public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
24         if(hasNext(pos)) return chainHandler.getChains().get(pos).doChain(chainHandler, ++pos, process);
25         return process.doProcess();
26     }
27 }
ChainHandler.java
1 public class ChainLoader {
2 
3     public static List<Chain> loadChain(){
4         List<Chain> chains = new ArrayList<>() ;
5         ServiceLoader<Chain> serviceLoader = ServiceLoader.load(Chain.class);
6         serviceLoader.forEach(chains::add);
7         return chains ;
8     }
9 }
ChainLoader.java
 1 package com.nancy.chain.auto.impl;
 2 
 3 import com.nancy.chain.auto.AbstractChain;
 4 import com.nancy.chain.auto.Chain;
 5 import com.nancy.chain.auto.ChainHandler;
 6 import com.nancy.chain.auto.Process;
 7 import java.util.List;
 8 
 9 public class HelloChain extends AbstractChain {
10 
11     @Override
12     public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
13         System.out.println("HelloChain被觸發了");
14         return chainHandler.doChain(chainHandler, pos, process);
15     }
16 
17     @Override
18     public Integer getOrder() {
19         return LOWEREST_ORDER-1 ;
20     }
21 
22 }
23 
24 package com.nancy.chain.auto.impl;
25 import com.nancy.chain.auto.AbstractChain;
26 import com.nancy.chain.auto.ChainHandler;
27 import com.nancy.chain.auto.Process;
28 
29 public class LogChain extends AbstractChain {
30 
31     @Override
32     public <T> T doChain(ChainHandler chainHandler, int pos, Process<T> process) {
33         System.out.println("LogChain被觸發了");
34         return chainHandler.doChain(chainHandler, pos, process);
35     }
36 
37     @Override
38     public Integer getOrder() {
39         return LOWEREST_ORDER ;
40     }
41 
42 }
鏈條

 JAVA SPI機制中的文件: META-INF/services/

com.nancy.chain.auto.impl.HelloChain
com.nancy.chain.auto.impl.LogChain

  觸發責任鏈:

package com.nancy.chain.auto;
import com.nancy.chain.auto.spi.ChainLoader;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        // 加載實現類
        List<Chain> chains = ChainLoader.loadChain() ;

        // 觸發
        ChainHandler handler = new ChainHandler(chains) ;
        Object res = handler.doChain(handler, 0, (Process<Object>) () -> 100) ;

        // 結果
        System.out.println("結果" + res);
    }
}

 結果:

HelloChain被觸發了
LogChain被觸發了
結果100

 

 3、注意點

  • 責任鏈模式會依據情況有很多變化。可以只由某個“鏈條”處理請求,或者每個鏈條只處理部分數據並交由后鏈條執行,直至責任鏈的終止。可以有結果返回或者沒有任何返回結果。
  • 責任鏈模式可以解耦客戶端和服務端,方便進行邏輯疊加。與觀察者模式最大不同在於前者觀察者是相互對等,之間沒有影響。而后者由鏈條串聯成線,鏈條之間可以建立起邏輯關系,完成某個功能。
  • 責任鏈模式當“鏈條”很長的時候會存在很大性能問題,設計之初應該考慮長度問題,長度限制在一定范圍內。 而責任鏈之間大多具有邏輯關系,不適用類似觀察者模式用異步線程處理的方式。
觸發責任鏈:
[Chùfā zérèn liàn:]
Trigger chain of responsibility:
Prototype原型模式
[Prototype yuánxíng móshì]
Prototype prototype model


免責聲明!

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



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