責任鏈模式(案例解析)(9)

一、概念

1、理解責任鏈模式

責任鏈模式是一種對象的行為模式,責任鏈模式實際上是一種處理請求的模式 它讓多個處理器(對象節點)都有機會處理該請求,請求通過這條加工鏈進行一步步的處理後。輸出最終的產品產出。

2、JDK中的責任鏈模式示例

讓我們看一下JDK中責任鏈模式的例子,然後我們將繼續實現這種模式的真實例子。我們知道在try-catch塊程式碼中我們可以有多個catch塊。這裡每個catch塊都是處理該特定異常的處理器。

因此當try塊中發生任何異常時,它會發送到第一個catch塊進行處理。如果catch塊無法處理它,它會將請求轉發到鏈中的下一個對象,即下一個catch塊。如果即使最後一個catch塊也無法處理它,那麼異常將被拋出鏈接到調用程式。

3、責任鏈模式使用

責任鏈模式怎麼使用呢?

  • 一個介面或者抽象類
  • 每個對象差異化處理
  • 對象鏈(數組)初始化(連起來)

二、舉例演示

我們在項目處理請求的時候,一個請求過來,我們可以進行 1)非空參數檢查 2)安全調用校驗 3)校驗黑名單 4)規則攔截對象 這些就是一個責任鏈。

按照上面的使用說明規則,來建好相應的類,進行演示。

1、一個介面或者抽象類

這個介面或者抽象類,需要:

  • 有一個指向責任下一個對象的屬性
  • 一個設置下一個對象的set方法
  • 給子類對象差異化實現的方法(如以下程式碼的doFilter方法)
/**
  * @Description: 定義一個介面或者抽象類
  */
public abstract class AbstractHandler {

    /**
     * 責任鏈中的下一個對象
     */
    private AbstractHandler nextHandler;
    
    // 具體參數攔截邏輯,給子類去實現
    public void filter(HttpServletRequest request, HttpServletResponse response) {
        //執行當前鏈
        doFilter(request, response);
        //如果還有下個鏈,執行下個鏈
        if (getNextHandler() != null) {
            getNextHandler().filter(request, response);
        }
    }

    //獲取下一個鏈對象
    public AbstractHandler getNextHandler() {
        return nextHandler;
    }
    
    //插入責任鏈的下一個對象
    public void setNextHandler(AbstractHandler nextHandler){
        this.nextHandler = nextHandler;
    }

    abstract void doFilter(HttpServletRequest request, HttpServletResponse response);
}

2、每個對象差異化處理

責任鏈上,每個對象的差異化處理,如本小節的業務場景,就有參數校驗對象、安全校驗對象、黑名單校驗對象、規則攔截對象。

/**
 * 1、參數校驗對象
 **/
@Component
@Order(1) //順序排第1,最先校驗
public class CheckParamFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("1、非空參數檢查");
    }
}

/**
 *  2、安全校驗對象
 */
@Component
@Order(2) //校驗順序排第2
public class CheckSecurityFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        //invoke Security check
        System.out.println("2、安全調用校驗");
    }
}

/**
 *  3、黑名單校驗對象
 */
@Component
@Order(3) //校驗順序排第3
public class CheckBlackFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        //invoke black list check
        System.out.println("3、校驗黑名單");
    }
}

/**
 *  4、規則攔截對象
 */
@Component
@Order(4) //校驗順序排第4
public class CheckRuleFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        //check rule
        System.out.println("4、規則攔截對象");
    }
}

3 對象鏈連起來(初始化)

/**
  * @Description: 對象鏈連起來(初始化)對象
  */
@Component("ChainPatternDemo")
public class ChainPatternDemo {

    //自動注入各個責任鏈的對象
    @Autowired
    private List<AbstractHandler> abstractHandleList;

    private AbstractHandler abstractHandler;

    //spring注入後自動執行,責任鏈的對象連接起來
    @PostConstruct
    public void initializeChainFilter(){

        for(int i = 0;i<abstractHandleList.size();i++){
            if(i == 0){
                //因為上面@Order(1)拍過序 所以第一個就是 非空參數檢查
                abstractHandler = abstractHandleList.get(0);
            }else{
                AbstractHandler currentHander = abstractHandleList.get(i - 1);
                AbstractHandler nextHander = abstractHandleList.get(i);
                currentHander.setNextHandler(nextHander);
            }
        }
    }

    //直接調用這個方法使用,返回最後處理好的response
    public HttpServletResponse exec(HttpServletRequest request, HttpServletResponse response) {
        //這裡 abstractHandler 就是第一個 接下來就會一個一個向下
        abstractHandler.filter(request, response);
        return response;
    }
}

4、使用演示

@RestController
public class PayController {

    @Autowired
    private ChainPatternDemo chainPatternDemo;

    @RequestMapping("/testHandler")
    public  void testHandler(HttpServletRequest req, HttpServletResponse resp){
        //調用責任鏈
        chainPatternDemo.exec(req,resp);
    }
}

運行結果

1、非空參數檢查
2、安全調用校驗
3、校驗黑名單
4、規則攔截對象

完美!

總結 當我們在開發中有一個對象需要多次處理的時候,就可以考慮用責任鏈設計模式,上面的示例也完全可以用於實際開發中。

參考

1、實戰!工作中常用到哪些設計模式 非常感謝!