設(shè)計模式之責(zé)任鏈模式
前言
之前覺得責(zé)任鏈模式是一種很高大上的模式泥耀,因為它不想策略模式那么隨處可見躺涝,也不想模板模式那么簡單明了疗我,我對責(zé)任鏈模式的了解僅限于一些框架中,如Shiro Filter中或者Dubbo Filter中琐脏,只是概念上的簡單認(rèn)識攒砖。最近項目中有一個需求,剛好有一個常見可以使用責(zé)任鏈模式日裙,所以就實踐了一把吹艇。
簡單說明
責(zé)任鏈模式類似與大家都玩過的游戲“擊鼓傳花”,請求的發(fā)起者就是開始游戲的人昂拂,而玩游戲的人呢則組成了一個處理者鏈受神,當(dāng)喊停的時候,花停留在哪一個人手里格侯,對應(yīng)就是請求被哪一個具體的人處理了鼻听。
請求的發(fā)起者發(fā)出請求,調(diào)用一個處理者联四,其實是一個處理鏈撑碴,而具體請求是被哪一個處理者處理了,請求的發(fā)起者是不知道也不關(guān)心的朝墩;而對于不同的請求醉拓,可能處理鏈也是不一樣的,不同的請求會有不同的處理鏈收苏,在執(zhí)行請求的過程中亿卤,動態(tài)的裝配處理鏈。我個人覺得責(zé)任鏈模式的核心就是責(zé)任鏈的裝配鹿霸。責(zé)任鏈的裝配的工作可以是有請求的調(diào)用者來裝配排吴,根據(jù)請求的信息,從處理者列表中選擇懦鼠、組裝責(zé)任鏈钻哩,我此次就是這么做的(因為相對比較簡單);也可以把這個裝配的工作交由框架來組裝葛闷,這樣職責(zé)更單一憋槐。
這樣就可以將請求的發(fā)起者和請求的具體處理者解耦双藕,根據(jù)請求的信息淑趾,每一次都進(jìn)行處理者的組裝,可以做到在運(yùn)行時動態(tài)組裝責(zé)任鏈 忧陪。
類圖

參與角色
Client:調(diào)用者
客戶端是請求的發(fā)起者扣泊,它負(fù)責(zé)調(diào)用一個AbstractHandler近范,具體請求是被責(zé)任鏈中的哪一個Handler處理了,客戶端是不清楚的延蟹。AbstractHandler:抽象的執(zhí)行類
此類負(fù)責(zé)定義抽象的Handler评矩,對外提供一個公共的Handler方法供客戶端調(diào)用ConcreteHandler:具體的執(zhí)行類
具體的執(zhí)行類只處理自己感興趣的部分,需要判斷當(dāng)前請求自己能否處理阱飘,如果可以處理斥杜,就自己處理,請求結(jié)束沥匈;如果處理不了蔗喂,就將請求轉(zhuǎn)發(fā)到下一個ConcreteHandler處理,如果沒有下一個Handler高帖,那么請求結(jié)束缰儿。
舉例
以此次項目舉例,代碼就不粘貼了散址。系統(tǒng)要對一個發(fā)票進(jìn)行規(guī)則判斷乖阵,而規(guī)則有很多種,并且不同種類發(fā)票的判斷規(guī)則是由不同規(guī)則組合而成的预麸。當(dāng)系統(tǒng)就收到一個發(fā)票的判斷請求時瞪浸,需要根據(jù)發(fā)票的信息,組裝相應(yīng)的校驗規(guī)則吏祸,如果有一個規(guī)則不滿足默终,那么發(fā)票就判斷為不符合條件的發(fā)票。這里不同的檢驗規(guī)則就是具體的校驗處理者犁罩,每一次發(fā)票過來齐蔽,就可以獲取對應(yīng)的校驗規(guī)則鏈,從而進(jìn)行處理床估。
遇到的一些問題
- 日志問題
由于是鏈?zhǔn)秸{(diào)用含滴,所以責(zé)任鏈模式一旦出現(xiàn)問題,調(diào)試起來相對來說麻煩一點丐巫,所以要在責(zé)任鏈調(diào)用過程中關(guān)鍵地方進(jìn)行日志記錄谈况,記錄執(zhí)行鏈的執(zhí)行記錄。方便出現(xiàn)問題定位問題递胧。 - 順序問題
在裝載責(zé)任鏈的時候碑韵,特別是使用每一個處理者持有下一個處理者引用的時候,一定要注意不要產(chǎn)生循環(huán)引用缎脾,否則就會形成死循環(huán)祝闻。