漫畫設(shè)計模式:什么是 “職責(zé)鏈模式” ?
—————? 第二天? —————
————————————
在一家公司里,有三個程序員,他們的名字分別是小A、小B、小C:
有一天,公司新來的產(chǎn)品經(jīng)理有一個新需求,但她不知道這個需求應(yīng)該由誰來負(fù)責(zé)。于是,她首先找到了小A:
于是,產(chǎn)品經(jīng)理又找到了小B:
于是,產(chǎn)品經(jīng)理又找到了小C:
像這樣,一個任務(wù)從小A轉(zhuǎn)移到小B,從小B轉(zhuǎn)移到小C,再由小C最終處理,形成了一個完整的任務(wù)處理鏈條:
在上面這個鏈條當(dāng)中,包含著不同的任務(wù)處理者。面對一個新任務(wù),每個任務(wù)處理者需要判斷自己能否處理該任務(wù),如果能處理,則處理并返回;如果不能處理,則轉(zhuǎn)交給下一個任務(wù)處理者,直到某一個任務(wù)處理者最終完成處理。這就是職責(zé)鏈模式的核心思想。
abstract?public?class?Handler?{
????protected?Handler?successor;
????public?void?setSuccessor(Handler?successor)?{
????????this.successor?=?successor;
????}
????abstract?String?handleRequest(String?msg);
}
從上面這個抽象類可以看出,每一個Handler對象都包含著一個successor成員,指向它的下一個任務(wù)處理者,就像鏈表節(jié)點的next指針一樣。
public?class?HandlerA?extends?Handler?{
????@Override
????String?handleRequest(String?msg)?{
????????if(msg.contains("a")){
????????????msg?=?msg.replace('a',?'*');
????????}?else?if(this.successor?!=?null){
????????????msg?=?this.successor.handleRequest(msg);
????????}
????????return?msg;
????}
}
public?class?HandlerB?extends?Handler?{
????@Override
????String?handleRequest(String?msg)?{
????????if(msg.contains("b")){
????????????msg?=?msg.replace('b',?'*');
????????}?else?if(this.successor?!=?null){
????????????msg?=?this.successor.handleRequest(msg);
????????}
????????return?msg;
????}
}
public?class?HandlerC?extends?Handler?{
????@Override
????String?handleRequest(String?msg)?{
????????if(msg.contains("c")){
????????????msg?=?msg.replace('c',?'*');
????????}?else?if(this.successor?!=?null){
????????????msg?=?this.successor.handleRequest(msg);
????????}
????????return?msg;
????}
}
在這三個Handler實現(xiàn)類中,做了相似的判斷:
如果傳入的消息字符串包含某個字母,則把對應(yīng)的字母替換成*。一旦某個Handler替換了自己所負(fù)責(zé)的字母,就直接結(jié)束整個鏈路;如果沒有自己所負(fù)責(zé)的字母,則指定下一個Handler繼續(xù)處理。
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????Handler?handlerA?=?new?HandlerA();
????????Handler?handlerB?=?new?HandlerB();
????????Handler?handlerC?=?new?HandlerC();
????????handlerA.setSuccessor(handlerB);
????????handlerB.setSuccessor(handlerC);
????????System.out.println(handlerA.handleRequest("apple"));
????????System.out.println(handlerA.handleRequest("bicycle"));
????????System.out.println(handlerA.handleRequest("color"));
????}
}
在客戶端代碼中,可以靈活設(shè)置整個鏈路和處理者的次序,然后直接調(diào)用第一個處理者的handleRequest方法,就相當(dāng)于啟動了整個鏈路。
做過Web開發(fā)的小伙伴都知道,當(dāng)客戶端對Web應(yīng)用發(fā)出HTTP請求的時候,會首先經(jīng)過Tomcat容器的一層層過濾器(Filter),過濾器會針對請求的訪問權(quán)限、參數(shù)合法性等方面進行驗證和過濾。
這一層一層過濾器的實現(xiàn),就使用了職責(zé)鏈模式。
熟悉SpringMVC框架源碼的小伙伴應(yīng)該都知道,客戶端的HTTP請求到了Web應(yīng)用之后,會被SpringMVC框架的DispatcherServlet類進行分發(fā),分發(fā)給Controller層的具體方法。
在進入Controller層的業(yè)務(wù)邏輯之前,以及執(zhí)行完業(yè)務(wù)邏輯之后,該請求都會經(jīng)過一系列的攔截器(Interceptor)。這一系列攔截器的處理流程,也同樣是職責(zé)鏈模式的實現(xiàn)。
—————END—————
喜歡本文的朋友,歡迎關(guān)注公眾號?程序員小灰,收看更多精彩內(nèi)容
點個[在看],是對小灰最大的支持!
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!