怎樣實際專案中運用責任鏈模式
1 模式概要
1.1 簡介
- 責任鏈模式為請求建立一個接收者物件鏈,每個接收者都包含對另一個接收者的引用,如果一個物件不能處理該請求,那麼它會把請求傳給下一個接收者,依此類推
- 責任鏈模式避免了請求的傳送者和接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止。
1.2 責任鏈模式優缺點
優點
降低耦合度。它將請求的傳送者和接收者解耦
簡化了物件,使得物件不需要知道鏈的結構
增強給物件指派職責的靈活性,允許動態地新增或者刪除責任鏈
增加新的請求處理類方便
缺點
不能保證請求一定被接收;
系統性能將受到一定影響,除錯時不方便,可能會造成迴圈呼叫
2 模式結構
2.1 物件定義
Handler(抽象處理者) : 定義一個處理請求的介面,提供對後續處理者的引用
ConcreteHandler(具體處理者) : 抽象處理者的子類,處理使用者請求,可選將請求處理掉還是傳給下家;在具體處理者中可以訪問鏈中下一個物件,以便請求的轉發
2.2 類圖及設計
責任鏈
程式碼詳解:
抽象處理者
具體處理者
在當前處理者物件無法處理時,將執行權傳給下一個處理者物件
Client 客戶端呼叫
ifelse
2.3 適用場景:
- 有多個物件可以處理同一個請求,具體哪個物件處理該請求由執行時刻自動確定
- 在不明確指定接收者的情況下,向多個物件中的某一個物件提交一個請求
- 可動態指定一組物件的處理請求
3 Spring中的過濾器
我們來分析Spring中Filter的 載入流程和執行流程
3.1 初始化流程
初始化過濾器載入資料流如下:
filter初始化載入時序圖
關鍵性程式碼
configure()
不管是資料走哪裡,最終會通過 System.arraycopy 陣列擴容,增加過濾器資訊到 private FilterMap[] array
最後呼叫StandardContext類中的 filterStart()
方法完成過濾器的初始化
3.2 執行過程
主要分兩步, 建立過濾器責任鏈 和 執行責任鏈
3.2.1 建立過程
建立filterChain方法主要在 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet)
中,部分程式碼講解:
在StandardWrapperValue類的 invoke()
方法中呼叫ApplicationFilterChai類的 createFilterChain()
方法
在ApplicationFilterChai類的 createFilterChain()
方法中呼叫ApplicationFilterChain類的 addFilter()
方法
在ApplicationFilterChain類的 addFilter()
方法中給ApplicationFilterConfig陣列賦值
生成呼叫鏈
3.2.2 執行責任鏈
呼叫ApplicationFilterChain的 doFilter()
方法中最後會呼叫一個 internalDoFilter()
方法,目的就是執行ApplicationFilterChain中的全部過濾器,從程式碼中可以發現它呼叫了 doFilter
,而在 doFilter
又會呼叫 internalDoFilter
從而使所有Filter都得以呼叫
這樣,一個完整的過濾器鏈就形成,然後進行呼叫
4 專案中的實際運用
業務場景
我們在專案中使用了阿里的MQ訊息中介軟體,來加快請求的響應時間和非同步解耦處理。RocktMQ主要可以按Topic來分割槽,然後按Tag分組,不同的業務區分不同的 tag
比如: 在此我向大家推薦一個架構學習交流裙。交流學習裙號:687810532,裡面會分享一些資深架構師錄製的視訊錄影
簡訊類的訊息 messageTag
手機推送訊息 pushTag
延時任務訊息 delayTag
等等。。。
常規寫法
ifelse
具體設計方案如下:
設計UML類圖
類圖
抽象公共監聽器 ,主要用到了單例模式獲取常量
具體監聽器 ,監聽器主要用於MQ監聽消費Topic
consume()
抽象處理者
具體處理者 :推送訊息Handler
具體處理者 :延時訂單處理Handler
模式工廠 HandlerFactory
getHandlerResponsibilityChain()
客戶端呼叫
getHandlerResponsibilityChain()