新聞中心
一、引言

創(chuàng)新互聯(lián)公司專(zhuān)注于河津網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供河津營(yíng)銷(xiāo)型網(wǎng)站建設(shè),河津網(wǎng)站制作、河津網(wǎng)頁(yè)設(shè)計(jì)、河津網(wǎng)站官網(wǎng)定制、小程序設(shè)計(jì)服務(wù),打造河津網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供河津網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。
初看責(zé)任鏈模式,心里不禁想起了一個(gè)以前聽(tīng)過(guò)的相聲:看牙。說(shuō)的是一個(gè)病人看牙的時(shí)候,醫(yī)生不小心把拔下的一個(gè)牙掉進(jìn)了病人嗓子里。病人因此樓上樓下的跑了好多科室,最后無(wú)果而終。
責(zé)任鏈模式就是這種“推卸”責(zé)任的模式,你的問(wèn)題在我這里能解決我就解決,不行就把你推給另一個(gè)對(duì)象。至于到底誰(shuí)解決了這個(gè)問(wèn)題了呢?我管呢!
二、定義與結(jié)構(gòu)
從名字上大概也能猜出這個(gè)模式的大概模樣——系統(tǒng)中將會(huì)存在多個(gè)有類(lèi)似處理能力的對(duì)象。當(dāng)一個(gè)請(qǐng)求觸發(fā)后,請(qǐng)求將在這些對(duì)象組成的鏈條中傳遞,直到找到最合適的“責(zé)任”對(duì)象,并進(jìn)行處理。
《設(shè)計(jì)模式》中給它的定義如下:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。
從定義上可以看出,責(zé)任鏈模式的提出是為了“解耦”,以應(yīng)變系統(tǒng)需求的變更和不明確性。
下面是《設(shè)計(jì)模式》中給出的適用范圍:
1) 有多個(gè)的對(duì)象可以處理一個(gè)請(qǐng)求,哪個(gè)對(duì)象處理該請(qǐng)求運(yùn)行時(shí)刻自動(dòng)確定。
2) 你想在不明確指定接收者的情況下,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求。
3) 可處理一個(gè)請(qǐng)求的對(duì)象集合應(yīng)被動(dòng)態(tài)指定。
責(zé)任鏈模式真的能給發(fā)送者和接收者之間解耦(這好像很神奇)嗎?先來(lái)看下它的組成角色。這個(gè)問(wèn)題我會(huì)在下面提及。
責(zé)任鏈模式由兩個(gè)角色組成:
1) 抽象處理者角色(Handler):它定義了一個(gè)處理請(qǐng)求的接口。當(dāng)然對(duì)于鏈子的不同實(shí)現(xiàn),也可以在這個(gè)角色中實(shí)現(xiàn)后繼鏈。
2) 具體處理者角色(Concrete Handler):實(shí)現(xiàn)抽象角色中定義的接口,并處理它所負(fù)責(zé)的請(qǐng)求。如果不能處理則訪問(wèn)它的后繼者。
至于類(lèi)圖不放也罷。畢竟就是一個(gè)繼承或者實(shí)現(xiàn)。
三、純與不純
責(zé)任鏈模式的純與不純的區(qū)別,就像黑貓、白貓的區(qū)別一樣。不要刻意的去使自己的代碼來(lái)符合一個(gè)模式的公式。只要能夠使代碼降低耦合、提高重用,滿(mǎn)足系統(tǒng)需求并能很好的適應(yīng)變化就好了。正所謂:管它黑貓白貓,抓住老鼠就是好貓!
純的責(zé)任鏈模式,規(guī)定一個(gè)具體處理者角色只能對(duì)請(qǐng)求作出兩種動(dòng)作:自己處理;傳給下家。不能出現(xiàn)處理了一部分,把剩下的傳給了下家的情況。而且請(qǐng)求在責(zé)任鏈中必須被處理,而不能出現(xiàn)無(wú)果而終的結(jié)局。
反之,則就是不純的責(zé)任鏈模式。
不純的責(zé)任鏈模式還算是責(zé)任鏈模式嗎?比如一個(gè)請(qǐng)求被捕獲后,每個(gè)具體處理者都嘗試去處理它,不管結(jié)果如何都將請(qǐng)求再次轉(zhuǎn)發(fā)。我認(rèn)為這種方式的實(shí)現(xiàn),算不算是責(zé)任鏈模式的一種倒不重要,重要的是我們也能從中體味到責(zé)任鏈模式的思想:通過(guò)將多個(gè)處理者之間建立聯(lián)系,來(lái)達(dá)到請(qǐng)求與具體的某個(gè)處理者的解耦。
#p#
下面的例子就是采用了上面提到的“不純的責(zé)任鏈模式”。
四、舉例
這個(gè)例子來(lái)源于項(xiàng)目中我剛剛完成的一個(gè)小功能點(diǎn)——“代號(hào)自動(dòng)生成器”。在項(xiàng)目中存在很多地方,比如:?jiǎn)T工工號(hào)、檔案代號(hào),要求客戶(hù)在使用時(shí)輸入。而這些代號(hào)對(duì)于一個(gè)特定的企業(yè)或者類(lèi)別,往往有一定的規(guī)則。因此可以讓用戶(hù)在系統(tǒng)參數(shù)中維護(hù)一定的規(guī)則,然后通過(guò)“代號(hào)自動(dòng)生成器”來(lái)給用戶(hù)生成代號(hào)。
根據(jù)初期需求,用戶(hù)代號(hào)中往往存在以下幾種變動(dòng)元素:年份、月份、日期、流水號(hào)。由于需求比較簡(jiǎn)單,因此考慮到用戶(hù)可能存在其他變動(dòng)元素,所以我打算在“被第一顆子彈擊中”后重構(gòu)一下現(xiàn)有的結(jié)構(gòu)。下面就是我在頭腦中演繹過(guò)的使用責(zé)任鏈模式的重構(gòu)。
這里只用來(lái)說(shuō)明下責(zé)任鏈模式的結(jié)構(gòu)和使用,因此不體現(xiàn)功能細(xì)節(jié)。
//這是抽象處理者角色
public interface CodeAutoParse {
//這里就是統(tǒng)一的處理請(qǐng)求使用的接口
String[] generateCode(String moduleCode, int number, String rule,String[] target) throws BaseException;
}
//這個(gè)為處理日期使用的具體處理者
public class DateAutoParse implements CodeAutoParse{
//獲取當(dāng)前時(shí)間
private final Calendar currentDate = Calendar.getInstance();
//這里用來(lái)注入下一個(gè)處理者,系統(tǒng)中采用的是Spring來(lái)管理的
private CodeAutoParse theNextParseOfDate;
public void setTheNextParseOfDate(CodeAutoParse theNextParseOfDate){
this.theNextParseOfDate = theNextParseOfDate ;
}
/*
*實(shí)現(xiàn)的處理請(qǐng)求的接口
*這個(gè)接口首先判斷用戶(hù)定義的格式是否有流水號(hào),有則解析,沒(méi)有則跳過(guò)
*下傳到下一個(gè)處理者
*/
public String[] generateCode(String moduleCode, int number, String rule, String[] target)
throws BaseException {
//這里省略了處理的業(yè)務(wù)
……
if(theNextParseOfDate != null)
return theNextParseOfDate.generateCode(moduleCode , number , rule, target)
else
return target;
}
其它具體處理者也是如此的結(jié)構(gòu),每一個(gè)里面都設(shè)置有一個(gè)用來(lái)存放下一個(gè)處理者的引用,不管你有沒(méi)有下一個(gè)處理者。
其實(shí)責(zé)任鏈模式本身的結(jié)構(gòu)和使用都沒(méi)有什么,就是一個(gè)繼承或者實(shí)現(xiàn)。在處理請(qǐng)求的時(shí)候,按照規(guī)定去調(diào)用下一個(gè)處理者。但是怎么來(lái)維護(hù)這樣一條鏈子呢?
《設(shè)計(jì)模式》一書(shū)中僅僅說(shuō)必須自己引入它,可以參考使用list或者map來(lái)進(jìn)行注冊(cè)。而在上面我使用spring來(lái)管理具體處理者角色的引入。當(dāng)有了新的處理者需要添加的時(shí)候,僅僅需要修改下配置文件。
五、其他
責(zé)任鏈模式優(yōu)點(diǎn),上面已經(jīng)體現(xiàn)出來(lái)了。無(wú)非就是降低了耦合、提高了靈活性。但是責(zé)任鏈模式可能會(huì)帶來(lái)一些額外的性能損耗,因?yàn)樗獜逆溩娱_(kāi)頭開(kāi)始遍歷。
本文標(biāo)題:深入淺出基于Java的責(zé)任鏈模式
網(wǎng)頁(yè)地址:http://www.5511xx.com/article/djhghsc.html


咨詢(xún)
建站咨詢(xún)
