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

雨點的名字發表於2021-10-29

一、概念

1、理解責任鏈模式

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

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

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、實戰!工作中常用到哪些設計模式 非常感謝!



相關文章