結合JDK學習設計模式-—行爲型設計模式——責任鏈模式

簡單地介紹:

責任鏈(Chain Of Responsibility
 

使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿着這

條鏈發送該請求,直到有一個對象處理它爲止。

沒有使用時的問題:

在介紹這個設計模式之前,先看看不使用這個模式,我們的代碼會是什麼樣子的.

    public static void main(String[] args) {
        LoginRequest request = new LoginRequest("age","年齡校驗");
        
    }
    
    public void checkLoginParam(LoginRequest request){
        if ("name".equals(request.getRequestType())){
            // 姓名的檢驗邏輯
        }else if ("age".equals(request.getRequestType())){
            // 年齡的校驗邏輯
        }
        
        //其他的校驗邏輯...............
    }

很容易發現 代碼會隨着後期校驗邏輯的增加 越來越長,越複雜。耦合性很高,而且新增校驗邏輯需要修改以前的代碼判斷分支,也違背了單一職責原則和開閉原則。

使用後的效果:

如何解決這個複雜校驗邏輯,還能滿足設計原則呢? 

推薦使用 責任鏈模式,當然,責任鏈模式的實現方法很多

javax.servlet.Filter#doFilter 使用 過濾器數組 移動數組索引實現 調用下一個過濾器  (核心類 ApplicationFilterChain)

我先採用最簡單的嵌套構造的方式來實現:

先看下類圖,有個總體的認知

  • 核心 任務處理父類

  • LoginHandler :定義處理請求的接口,並且實現後繼鏈(handler)
public abstract class LoginHandler {
    protected LoginHandler handler;

    public LoginHandler(LoginHandler handler){
        this.handler = handler;
    }

    protected abstract void handlerLoginRequest(LoginRequest request);
}

具體的處理器類:

1. 年齡校驗邏輯

public class LoginAgeHandler extends LoginHandler {

    public LoginAgeHandler(LoginHandler handler){
        super(handler);
    }

    @Override
    protected void handlerLoginRequest(LoginRequest request) {
        if ("age".equals(request.getRequestType())){
            System.out.println("LoginAgeHandler----》 " + request.getTaskName());
            return;
        }

        if (null != handler){
            handler.handlerLoginRequest(request);
        }
    }
}

2. 姓名校驗邏輯: 

public class LoginNameHandler extends LoginHandler {

    public LoginNameHandler(LoginHandler handler){
        super(handler);
    }

    /**
     *  處理完成自己的邏輯後 判斷是否需要交給下一個處理器來處理
     * @param request
     */
    @Override
    protected void handlerLoginRequest(LoginRequest request) {
        if ("name".equals(request.getRequestType())){
           // query user from db, if exist execute next stop
            System.out.println("LoginNameHandler--》" + request.getTaskName());
        }

        // 交給下一個處理器處理 請求任務
        if (null != handler){
            handler.handlerLoginRequest(request);
        }
    }
}

待處理的任務類:

public class LoginRequest {
    private String requestType;
    private String taskName;

    public LoginRequest(String requestType, String taskName) {
        this.requestType = requestType;
        this.taskName = taskName;
    }

    public String getRequestType() {
        return requestType;
    }

    public String getTaskName() {
        return taskName;
    }
}

最後,我們做一下調用測試:

package com.cheri.designpattern.cases.action;

/**
 *
 * 嵌套過濾器,內部依次判斷是否存在 執行過濾器
 * @author Aaron Du
 * @version V1.0
 * @date 2020/5/1 15:08
 **/
public class Client {

    public static void main(String[] args) {
        LoginRequest request1 = new LoginRequest("name","用戶名檢查");
        LoginRequest request2 = new LoginRequest("age","年齡檢查");


        LoginHandler ageHandler = new LoginAgeHandler(null);
        LoginHandler nameHandler =  new LoginNameHandler(ageHandler);

        nameHandler.handlerLoginRequest(request1);
        nameHandler.handlerLoginRequest(request2);


    }
}

可以清楚的看到,對應處理器只處理自己負責的處理邏輯。

我們看JDK如何使用責任鏈模式的:

一般我們使用一個過濾器時都是如下處理:實現Filter接口重寫doFilter方法

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 自己過濾器處理邏輯

        // 調用下一個過濾器
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

在Tomcat容器中,會將所有的過濾器加載到  ApplicationFilterChain中的 

private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]數組中

 下面是添加過濾器到數組的方法:

 

當我們調用 

chain.doFilter(request,response);來調用下一個過濾器時,內部會調用

ApplicationFilterChain的doFilter方法

我們會看到,內部會通過數組索引的遞增來逐個調用下一個過濾器,實現過濾器逐個調用的效果。這個是過濾器Filter對

責任鏈模式的實現方法。

 

總結:1.要有待處理的任務對象。

             2.要有統一的處理器基類 且 基類中要維護任務和一個抽象的處理方法,不同的子類都實現不同的處理邏輯。

             3. 執行鏈的維護可以使用數據也可以採用構造嵌套的方式

 

 

 

 

 

 

 

 

 

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