設計模式之責任鏈模式講解
前言
很多框架如mybatis,servlet的filter,dubbo,安全框架諸如Spring security、apache shiro都會用到設計模式中的責任鏈模式,所以學習責任鏈模式成為幫助你學習以上這些框架的一個好的手段之一。今天我們就來了解一下責任鏈模式。
定義
如果有多個物件(Handler)都有機會處理資料來源(RequestSource,這裡不是單純的資料庫資料來源,可以是一個請求,總之是來源),責任鏈可以使資料的傳送者和接收者解耦,資料沿著責任鏈傳遞,直到有一個物件處理了它為止。 上去形成了一條流水線的鏈條,所以稱之為責任鏈,但是不僅僅侷限於鏈條,還可以成樹形或者環形,這取決於你的業務設計。
場景
外掛設計、攔截器、過濾器等一些針對切入點的特定鏈式處理。都可以使用責任鏈模式。
兩種實現方式
兩種方式的不同主要是定義處理鏈的順序和結構的不同,接下來我們來看看這三種方式。
通過處理器集合來定義處理順序
好處在於可以集中管理處理器,指責單一。非常容易理解,容易實現。缺點是如果新增處理器(Handler)勢必影響已有的處理器,只能順序執行。處理流程是這樣的:
接下來用程式碼來實現一下此模式:
HandlerChain 負責維護呼叫鏈條的順序,這裡預設實現用List來管理Handler
public interface HandlerChain { /** * 呼叫handler 處理 source. * * @param requestSource the request source */ void doChain(RequestSource requestSource); } // 實現 public class DefaultHandlerChain implements HandlerChain { // 當前handler指標的位置 private int pos = 0; private List<Handler> handlers = new ArrayList<>(); public void addHandler(Handler handler) { handlers.add(handler); } @Override public void doChain(RequestSource requestSource) { int size = handlers.size(); if (pos < size) { //注意對pos的處理 Handler handler = handlers.get(pos++); handler.doHandler(requestSource, this); } } }
Handler是處理鏈的節點抽象,是資料來源(RequestSource)的具體處理者,它負責對資料的處理以及決定是否進入下一個Handler。
public interface Handler { /** * Do handler. * * @param requestSource 資料來源 * @param handlerChain 傳入當前的Chain進行類似遞迴式的呼叫。 */ void doHandler(RequestSource requestSource,HandlerChain handlerChain); } // 其中一個實現 public class HeaderHandler implements Handler { @Override public void doHandler(RequestSource requestSource, HandlerChain handlerChain) { // 處理資料 Integer header = requestSource.getHeader(); System.out.println("header handler= " + header); //繼續下一個 你可以根據條件來決定是否繼續進行chain handlerChain.doChain(requestSource); } }
利用連結串列的指標特性
這裡利用了連結串列的一部分特點,通過在當前的Handler指定下一個Handler來作為指標,相比較上面而言,Handler更自治,在節點的處理上更加靈活。
Handler負責指標以及邏輯處理:
public interface Handler {
/**
* 指標指向下一個處理節點.
*
* @return the next
*/
Handler getNext();
/**
* 處理具體邏輯.
*
* @param requestSource the request source
*/
void doHandler(RequestSource requestSource);
}
// 實現
public class HeaderHandler implements Handler {
private Handler next;
public HeaderHandler(Handler next) {
this.next = next;
}
@Override
public Handler getNext() {
return next;
}
@Override
public void doHandler(RequestSource requestSource) {
Integer header = requestSource.getHeader();
System.out.println("header = " + header);
if (next != null) {
next.doHandler(requestSource);
}
}
}
總結
責任鏈模式在各種常見框架中非常常見。所以建議各位在對此設計模式進行認真學習。相關程式碼在公眾號:Felordcn 同名文章中提供。
關注公眾號:碼農小胖哥 獲