【設計模式】責任是責任,鏈是鏈,責任鏈模式是什麼?

這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰java

1、什麼是責任鏈模式
1.先看看百度百科是怎麼解釋的

責任鏈模式是一種設計模式。在責任鏈模式裏,不少對象由每個對象對其下家的引用而鏈接起來造成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪個對象最終處理這個請求,這使得系統能夠在不影響客戶端的狀況下動態地從新組織和分配責任。 ——百度百科spring

咱們能夠理解到,責任鏈就是多個對象一塊兒共同對一個請求進行處理,這裏還提到的,直到鏈上的某一個對象決定處理此請求。若是隻是有一個對象對請求進行處理的話,那爲何要花費這麼大的力氣去組成這一條責任鏈呢?這不是畫蛇添足嗎?設計模式

2.我對責任鏈的見解

首先,責任鏈的這個設計模式,確定是將一個請求分散給多個對象處理,爲了更加的直觀方便,因而將處理對象串成一條鏈條,讓它們一直調用下家來進行處理這個請求。 其次,責任鏈並非只有一個對象決定對請求進行處理,而是所有對象共同對這個請求進行處理,只是分別在不一樣的維度上而已。tomcat

簡單地畫個圖做爲對責任鏈的描述 在這裏插入圖片描述markdown

3.使用責任鏈的優缺點
優勢
  1. 讓每一個類更加地專一本身的責任。
  2. 使編碼過程更加的清晰。
  3. 下降耦合度。下降了代碼的複雜度
  4. 新增或修改更加方便
缺點
  1. 處理存在延遲
  2. 不能保證請求必定被處理
  3. 責任鏈較長會影響系統性能
  4. 進行代碼調試時不方便
原則

「+」表明遵照,「-」表明不遵照或者不相關ide

原則 開放封閉 單一職責 迪米特 里氏替換 依賴倒置 接口隔離 合成複用
+ + - - + - -
2、加強型責任鏈(過濾器)

由於感受跟加強型代理特別像,就比較大膽地將名字取成了加強型責任鏈,它也能夠叫過濾器。工具

1.特色
  1. 最終處理對象不變
  2. 使用習慣不變
  3. 業務無關性
  4. 附加新功能
  5. 請求必定會被處理

總的來講,加強型責任鏈的處理對象仍然是隻有一個,很符合百度百科的解釋,就是整一條責任鏈中,只有最後一個對象纔會對請求進行處理,其餘的都是在做一些記錄,或者是上鎖,都是一切無關業務的操做。加強型責任鏈更加側重的點是無關業務邏輯的操做。post

2.常見的例子
  1. tomcat中的Filter接口,在請求的時候採用了這種加強型責任鏈,最終處理請求的對象沒有改變,它是一層一層地將request和response傳遞給servlet對象處理的。
  2. struts2中也存在過濾器,具體用來幹嗎的,我也想不起來了,好像是用來校驗的。
3、攔截器責任鏈
1.特色
  1. 最終處理對象不變
  2. 使用習慣不變
  3. 改變業務邏輯
  4. 請求不必定被處理

總的來講,攔截器責任鏈會影響到業務的邏輯,一旦其中的一個對象驗證時不符合條件,就會中斷整個請求,就像是一系列的if包裹在一塊兒。攔截器責任鏈更加側重的點是業務邏輯。性能

2.常見的例子
  1. HandlerInterceptorAdapter類
  2. 一樣是struts2裏面也有攔截器,能夠用做攔截用戶無登錄進入網站。
  3. spring中也有攔截器
4、過程型責任鏈(pipeline責任鏈)
1.特色
  1. 處理對象不單一
  2. 責任鏈對象順序有要求
  3. 使用更加方便
  4. 業務無關性
  5. 請求必定會被處理

總的來講,過程型責任鏈就是將一個請求分給多個對象進行處理,處理的順序有些會存在嚴格要求,當所有對象都進行了處理以後就會返回。有點像連接型代理,對多個方法進行了封裝,可是過程型責任鏈對處理的順序有要求。過程型責任鏈更加側重的點是處理的過程。測試

2.常見的例子
  1. Jenkins打包工具,它就是將源代碼處理成字節碼,再打包成wai包,而後發佈。
5、總結

加強型責任鏈更加側重的點是無關業務邏輯的操做。 攔截器責任鏈更加側重的點是業務邏輯。 過程型責任鏈更加側重的點是處理的過程。 這三個責任鏈分別從三個維度出發,造成了各有特點的責任鏈。 不排除之後會出現更多的責任鏈,可是它們的本質都是從不一樣維度對一個請求進行處理,它們的形式都是一個鏈條。

6、責任鏈簡單的實現方式

這是仿照tomcat裏的過濾器責任鏈來實現的,想要實現其餘的責任鏈,作出一些修改便可。

  1. 先建立一個Filter接口,做爲責任鏈中存放對象的原型
package responsibilitychain;
​
/**
 * @author xxj
 * 過濾器
 */
public interface Filter {
    /**
     * 責任鏈中最終執行的方法
     * @param object 傳遞的須要處理的對象
     * @return 改爲boolean的話就是攔截器了,
     */
    void doFilter(Object object);
}
複製代碼
  1. 建立一個FilterChain類,做爲責任鏈管理器
package responsibilitychain;
​
import java.util.ArrayList;
import java.util.List;
​
/**
 * @author xxj
 * 責任鏈管理器
 */
public class FilterChain implements Filter {
    List<Filter> list =new ArrayList<>();
    public void addFilter(Filter filter){
        list.add(filter);
    }
    @Override
    public void doFilter(Object object) {
        list.forEach(f -> f.doFilter(object));
    }
}
​
複製代碼
  1. 使用責任鏈 每一個責任鏈對象都須要單首創建一個類,這個類須要實現Filter接口
package responsibilitychain;
​
/**
 * @author xxj
 * 測試責任鏈
 * 對一個String對象進行修改
 */
public class test {
    public static void main(String[] args){
        //建立責任鏈管理器
        FilterChain filterChain=new FilterChain();
        //添加責任鏈
        filterChain.addFilter(new FirstFilter());
        filterChain.addFilter(new SecondFilter());
        filterChain.addFilter(new LastFilter());
        //調用責任鏈
        String string="   aaa    ";
        filterChain.doFilter(string);
    }
    static class FirstFilter implements Filter{
        @Override
        public void doFilter(Object object) {
            //強轉成String
            String string=(String)object;
            //輸出String的長度
            System.out.println(string.length());
​
        }
    }
    static class SecondFilter implements Filter{
        @Override
        public void doFilter(Object object) {
            //強轉成String
            String string=(String)object;
            //去掉空格
            string=string.trim();
            //再輸出長度
            System.out.println(string.length());
        }
    }
    static class LastFilter implements Filter{
        @Override
        public void doFilter(Object object) {
            //強轉成String
            String string=(String)object;
            //輸出string
            System.out.println(string);
​
        }
    }
}
複製代碼
  1. 輸出的結果
10
3
   aaa    
​
複製代碼

責任鏈模式除了這種實現方式以外,還有一種實現方式,定義跟過濾器同樣的接口,名稱的話叫chain也行,而後定義一些行爲,這裏的行爲是須要跟你最終想要使用的對象同樣,例如一個數據對象LogData有get和set方法,那這個接口就要有get和set方法,而後實現一系列的chain類,這些chain類內部須要聲明一個chain的成員變量,這個成員用於指向下一個chain對象,還有get或set方法都須要去調用這個chain對象的get或set方法,接下來就是要組成咱們的責任鏈了,把一個個chain實現類的對象組成一條鏈子,在建立對象時就要傳遞下一個責任鏈節點的對象進入,直到最終想要使用的對象。

——————————————————————————————

你知道的越多,不知道的就越多。

若是本文章內容有問題,請直接評論或者私信我。若是以爲我寫得還不錯的話,點個贊也是對個人支持哦

未經容許,不得轉載!

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息