淺談責任鏈模式

一、什麼是責任鏈

1.先看看百度百科是怎麼解釋的

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

我們可以理解到,責任鏈就是多個對象一起共同對一個請求進行處理,這裏還提到的,直到鏈上的某一個對象決定處理此請求。如果只是有一個對象對請求進行處理的話,那爲什麼要話費這麼大的力氣去組成這一條責任鏈呢?這不是多此一舉嗎?

2.我對責任鏈的看法

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

3.使用責任鏈的優缺點

優點

  1. 讓每個類更加地專注自己的責任。
  2. 使編碼過程更加的清晰。
  3. 降低耦合度。降低了代碼的複雜度
  4. 新增或修改更加方便

缺點

  1. 處理存在延遲
  2. 不能保證請求一定被處理
  3. 責任鏈較長會影響系統性能
  4. 進行代碼調試時不方便

二、增強型責任鏈(過濾器)

因爲感覺跟增強型代理特別像,就比較大膽地將名字取成了增強型責任鏈,它也可以叫過濾器。

1.特點

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

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

2.常見的例子

  1. tomcat中的Filter接口,在請求的時候採用了這種增強型責任鏈,最終處理請求的對象沒有改變,它是一層一層地將request和response傳遞給servlet對象處理的。
  2. struts2中也存在過濾器,具體用來幹嘛的,我也想不起來了,好像是用來校驗的。

三、攔截器責任鏈

1.特點

  1. 最終處理對象不變
  2. 使用習慣不變
  3. 改變業務邏輯
  4. 請求不一定被處理

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

2.常見的例子

  1. HandlerInterceptorAdapter類
  2. 同樣是struts2裏面也有攔截器,可以用作攔截用戶無登陸進入網站。
  3. spring中也有攔截器
  4. jvm中的雙親委派

四、過程型責任鏈(pipeline責任鏈)

1.特點

  1. 處理對象不單一
  2. 責任鏈對象順序有要求
  3. 使用更加方便
  4. 業務無關性
  5. 請求一定會被處理

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

2.常見的例子

  1. Jenkins打包工具,它就是將源代碼處理成字節碼,再打包成wai包,然後發佈。

五、總結

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

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

這是仿照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    

——————————————————————————————
如果本文章內容有問題,請直接評論或者私信我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章