調(diào)用像鏈子,責(zé)任鏈模式
0x01:責(zé)任鏈模式簡(jiǎn)介
在責(zé)任鏈模式中,很多對(duì)象由每一個(gè)對(duì)象對(duì)其下家的引用而連接起來形成一條鏈。請(qǐng)求在這個(gè)鏈上進(jìn)行傳遞,直到鏈上的某一個(gè)對(duì)象決定處理此請(qǐng)求。發(fā)出這個(gè)請(qǐng)求的客戶端并不知道鏈上的哪一個(gè)對(duì)象最終處理這個(gè)請(qǐng)求,這使得系統(tǒng)可以在不影響客戶端的情況下動(dòng)態(tài)地重新組織和分配責(zé)任。責(zé)任鏈模式的UML類圖如下:

其中,Handler是抽象處理者,定義了一個(gè)處理請(qǐng)求的接口;ConcreteHandler是具體處理者,處理它所負(fù)責(zé)的請(qǐng)求,可訪問它的后繼者,如果可處理該請(qǐng)求就處理,否則就將該請(qǐng)求轉(zhuǎn)發(fā)給它的后繼者。主要角色如下:
抽象處理者(Handler):定義出一個(gè)處理請(qǐng)求的接口。如果需要接口可以定義出一個(gè)方法以設(shè)定和返回對(duì)下一個(gè)處理對(duì)象的引用。這個(gè)角色通常由一個(gè)抽象類或者接口實(shí)現(xiàn)。Handler類的聚合關(guān)系給出了具體子類對(duì)下一個(gè)處理對(duì)象的引用,抽象方法handleRequest()規(guī)范了子類處理請(qǐng)求的操作。
具體處理者(ConcreteHandler):具體處理者接到請(qǐng)求后,可以選擇將請(qǐng)求處理掉,或者將請(qǐng)求傳給下一個(gè)Handler處理。由于具體處理者持有對(duì)一個(gè)處理對(duì)象的引用,因此,如果需要具體處理者可以訪問下一個(gè)處理對(duì)象。
0x02:責(zé)任鏈模式實(shí)現(xiàn)
在工作中,免不了需要進(jìn)行報(bào)銷。現(xiàn)在與報(bào)銷這個(gè)業(yè)務(wù)流程來實(shí)現(xiàn)責(zé)任鏈模式。約定如下:
報(bào)銷金額 0?~ 1W 直屬上司審批即可,報(bào)銷級(jí)別為1;
報(bào)銷金額 1W+?~ 5W 部門經(jīng)理審批即可,報(bào)銷級(jí)別為2;
報(bào)銷金額 5W+?公司負(fù)責(zé)人審批,報(bào)銷級(jí)別為3;
Request類負(fù)責(zé)封裝請(qǐng)求,具體內(nèi)容需根據(jù)業(yè)務(wù)產(chǎn)生
public?class?Request?{
????private?int?level;
????public?Request(int?level)?{
????????this.level?=?level;
????}
????public?void?setLevel(int?level)?{
????????this.level?=?level;
????}
????public?int?getLevel()?{
????????????return?this.level;
????}
}
Response類負(fù)責(zé)封裝鏈中返回的結(jié)果,具體內(nèi)容需根據(jù)業(yè)務(wù)產(chǎn)生
//處理者返回的數(shù)據(jù)
public?class?Response?{
????private?int?result;
????public?Response(int?result)?{
????????this.result?=?result;
????}
????public?int?getResult()?{
????????return?result;
????}
????public?void?setResult(int?result)?{
????????this.result?=?result;
????}
?}
抽象處理者(Handler)
public?abstract?class?Handler?{
????//下一個(gè)處理者
????private?Handler?nextHandler;??
????public?final?Response?handlerMessage(Request?request)?{
????????Response?response?=?null;
????????if(this.getLevel()?==?request.getLevel())?{????//判斷是否是自己的處理級(jí)別
????????????response?=?this.process(request);
????????}?else?{
????????????if(this.nextHandler?!=?null)?{????//下一處理者不為空
????????????????response?=?this.nextHandler.handlerMessage(request);
????????????}?else?{
????????????????//沒有適當(dāng)?shù)奶幚碚撸瑯I(yè)務(wù)自行處理
????????????}
????????}
????????return?response;
????}
????//設(shè)定下一個(gè)處理者
????public?void?setNext(Handler?handler)?{
????????this.nextHandler?=?handler;
????}
????//每個(gè)處理者可以處理的報(bào)銷等級(jí)
????protected?abstract?int?getLevel();
????//每個(gè)處理者都必須實(shí)現(xiàn)的處理任務(wù)
????protected?abstract?Response?process(Request?request);
}
具體處理者(ConcreteHandler)
直屬上司
/**
?*?直屬上司
?*
?*/
public?class?DirectorManager?extends?Handler?{
????@Override
????protected?int?getLevel()?{
????????return?1;
????}
????@Override
????protected?Response?process(Request?request)?{
????????System.out.println("DirectorManager?process>>");
????????return?new?Response(1);
????}
}
部門長(zhǎng)
/**
?*?直屬上司
?*
?*/
public?class?DeptManager?extends?Handler?{
????@Override
????protected?int?getLevel()?{
????????return?2;
????}
????@Override
????protected?Response?process(Request?request)?{
????????System.out.println("DeptManager?process>>");
????????return?new?Response(2);
????}
}
公司負(fù)責(zé)人
/**
?*?直屬上司
?*
?*/
public?class?CompanyManager?extends?Handler?{
????@Override
????protected?int?getLevel()?{
????????return?3;
????}
????@Override
????protected?Response?process(Request?request)?{
????????System.out.println("CompanyManager?process>>");
????????return?new?Response(3);
????}
}
責(zé)任鏈模式測(cè)試代碼
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????Handler?handler1?=?new?DirectorManager();
????????Handler?handler2?=?new?DeptManager();
????????Handler?handler3?=?new?CompanyManager();
????????//設(shè)置鏈中的階段順序?1->2->3
????????handler1.setNext(handler2);
????????handler2.setNext(handler3);
????????//提交請(qǐng)求返回結(jié)果
????????Response?response?=?handler1.handlerMessage(new?Request(2));
????}
}
0x03:責(zé)任鏈模式在框架的運(yùn)用
責(zé)任鏈模式的運(yùn)用可是說非常廣泛,下面來了解一下都有哪些框架使用了該設(shè)計(jì)模式
J2EE
在Servlet技術(shù)中,分別定義了一個(gè)?Filter 和 FilterChain 接口
Filter接口
public?interface?Filter?{
????default?public?void?init(FilterConfig?filterConfig)?throws?ServletException?{}
????public?void?doFilter(ServletRequest?request,?ServletResponse?response,
?????????????????????????FilterChain?chain)
????????????throws?IOException,?ServletException;
????default?public?void?destroy()?{}
}
FilterChain接口
public?interface?FilterChain?{
????public?void?doFilter(ServletRequest?request,?ServletResponse?response)
????????????throws?IOException,?ServletException;
}
核心處理類ApplicationFilterChain
public?final?class?ApplicationFilterChain?implements?FilterChain?{
?@Override
????public?void?doFilter(ServletRequest?request,?ServletResponse?response)
????????//?省略
????}
????private?void?internalDoFilter(ServletRequest?request,
??????????????????????????????????ServletResponse?response)
????????throws?IOException,?ServletException?{
??????????//省略
????}
????//省略
}
在使用Filter時(shí),如果需要交給下一個(gè)Filter處理,都會(huì)調(diào)用如下一段代碼:
chain.doFilter(request,?response);
SpringMVC
如果有看過SpringMVC的DispatcherServlet類的源碼,可以看到如下一段代碼

HandlerExecutionChain類是一個(gè)責(zé)任鏈,其中的方法 applyPreHandler() , applyPostHandle() 和 triggerAfterCompletion() 相當(dāng)于具體的處理類;在 DispatcherServlet 類的 doDispatch() 方法中進(jìn)行條件判斷實(shí)現(xiàn)處理的傳遞。如果想深入了解 HandlerExecutionChain 類的調(diào)用關(guān)系,可以跟蹤一下 DispatcherServlet 類的 doDispatch() 方法。

喜歡,在看
