學(xué)而時(shí)習(xí)之熙涤,溫故而知新惋砂。這句話用在設(shè)計(jì)模式上真是太恰當(dāng)不過了!博主從上大二的時(shí)候就開始閱讀設(shè)計(jì)模式厢洞,當(dāng)時(shí)對(duì)面向?qū)ο蟮乃季S理解的不是很深刻仇让。所以一些設(shè)計(jì)模式弄得一知半解,只知其形而不知其神犀变。工作之余也沒有放棄過對(duì)設(shè)計(jì)模式的學(xué)習(xí)和琢磨妹孙,每次閱讀相關(guān)的設(shè)計(jì)模式總有不同的心得體會(huì)秋柄。收貨頗多获枝。所以在此建議讀者也要時(shí)不時(shí)翻看下設(shè)計(jì)模式。從中演化出適合自己的模式出來骇笔∈〉辏可以說設(shè)計(jì)模式是面向?qū)ο笏季S的集大成者嚣崭。越閱讀越有味道。
閑言少敘懦傍,本篇博文就簡(jiǎn)單的梳理下博主對(duì)責(zé)任鏈模式的理解和體會(huì)雹舀,如有不當(dāng)之處歡迎批評(píng)指正。正規(guī)的責(zé)任鏈模式有如下兩點(diǎn):
1粗俱、責(zé)任鏈一般有兩種對(duì)象说榆,一個(gè)是請(qǐng)求者。一個(gè)是處理者寸认。需要注意的是<font color="#ff00ff">處理者是有可能返回處理結(jié)果給請(qǐng)求者的</font>签财。查閱了好多篇關(guān)于責(zé)任鏈模式的文章,這點(diǎn)好像都沒有提及偏塞。
2唱蒸、多個(gè)對(duì)象中,每個(gè)對(duì)象都持有下一個(gè)對(duì)象的引用灸叼,這就構(gòu)成了鏈這種結(jié)構(gòu)神汹。(但是一定要如此嗎?后面會(huì)有說明)
因?yàn)樵诖a設(shè)計(jì)中我們會(huì)將處理者抽象出一個(gè)接口古今,所以實(shí)現(xiàn)這個(gè)接口的處理者可能屁魏。
責(zé)任鏈模式的主要工作就是在眾多的處理者中找到能處理當(dāng)前請(qǐng)求的那一個(gè)處理者對(duì)象!所以具體的處理者需要持有下一個(gè)處理者的引用沧卢!ConcreteHandler1
偽代碼如下:
public class ConcreteHandler1 extends Handler{
protected Handler nextHandler;//下一個(gè)處理者
@Override
public void handleRequest() {
if ( 符合處理要求) {
//進(jìn)行處理 邏輯
doMyJob();
} else {//不符合則交給下一個(gè)處理者
nextHandler.handleRequest();
}
}
}
責(zé)任鏈模式的一個(gè)特點(diǎn)就是<font color="#ff00ff">當(dāng)前處理者必須知道下一個(gè)處理者是誰(shuí)</font>蚁堤。初始化當(dāng)前處理者的時(shí)候也要把下一個(gè)處理者進(jìn)行綁定。其實(shí)如果當(dāng)前處理者不需要知道下一個(gè)處理者是誰(shuí)的話但狭,完全可以這么調(diào)用:
List<Handler> handlers=initHandlers();
for(Handler currentHandler:handlers){
if(currentHandler.isHandlebale()){//如果當(dāng)前能夠處理當(dāng)前請(qǐng)求
currentHandler.handleRequest();
break;//處理完畢披诗,跳出循環(huán)
}
}
上面這個(gè)for循環(huán)的責(zé)任鏈模式甚至可以說是ConcreteHandler1
代碼的擴(kuò)展,因?yàn)樗容^靈活立磁!ConcreteHandler1
在設(shè)計(jì)的時(shí)候需要指定下一個(gè)處理者呈队。而for循環(huán)遍歷的這種方式,我們只需要在initHandlers()
初始化處理者集合的時(shí)候唱歧,合理的安排好集合中的順序即可將這種擊鼓傳花的游戲玩下去宪摧。
考慮到另外一個(gè)場(chǎng)景:公司的請(qǐng)假系統(tǒng),需要層層批準(zhǔn),上一個(gè)部分批準(zhǔn)后需要把后續(xù)流程交個(gè)下一個(gè)部門颅崩,這種工作模式最適合責(zé)任鏈模式几于。但是如果需要層層批準(zhǔn)的話,那么上面的偽代碼ConcreteHandler1
就不符合沿后,因?yàn)樗幚硗陮儆谧约旱墓ぷ骱缶筒煌髠髁搜嘏恚跃托枰M(jìn)行如下改造:
public class ConcreteHandler1 extends Handler{
protected Handler nextHandler;//下一個(gè)處理者
@Override
public void handleRequest() {
//處理屬于我自己分內(nèi)的邏輯
doMyJob();
//處理完成后,后續(xù)流程交給下一個(gè)處理者
nextHandler.handleRequest();
}
}
在平時(shí)寫代碼中尖滚,其實(shí)自己很少用過這種設(shè)計(jì)模式喉刘。但是有一個(gè)框架把這個(gè)模式用的很出彩瞧柔,那就是Okhttp框架。其攔截器的設(shè)計(jì)理念堪稱責(zé)任鏈模式的靈活使用的典范睦裳,關(guān)于Okhttp框架的分析可參考博主的專欄okhttp源碼解析造锅。
在OKhttp的攔截器中,發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求廉邑,我們將請(qǐng)求封裝成Request對(duì)象哥蔚。交給攔截器中的某個(gè)攔截器,該攔截器處理完自己的工作之后蛛蒙,根據(jù)具體業(yè)務(wù)邏輯判斷是否需要交給下一個(gè)攔截器肺素。如果不需要,就將處理結(jié)果Response對(duì)象返回給請(qǐng)求者宇驾!其流程圖如下圖所示:
到此為止倍靡,關(guān)于責(zé)任鏈模式的心得體會(huì)書寫完畢。后期可能隨著自己體會(huì)的不斷加深课舍,該篇博文需要進(jìn)行修改塌西,敬請(qǐng)期待吧。