目錄
職責鏈模式
小俱求實習
結構圖
實例
職責鏈模式優點
職責鏈模式缺點
使用場景
1.springmvc流程
?2.mybatis的執行流程
3.spring的過濾器和攔截器
職責鏈模式
使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關系。將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它。
?一個請求有多個對象可以處理,但每個對象的處理條件或權限不同,為了避免請求發送者與多個請求處理者耦合在一起,將所有請求的處理者通過前一對象記住其下一個對象的引用而連成一條鏈;當有請求發生時,可將請求沿著這條鏈傳遞,直到有對象處理它為止。
概念可能不容易理解,我先舉一個例子說說親身體會的一件事,就叫小俱求實習吧。
小俱求實習
背景:2024上半年? 小俱正值大三下學期
在這個92?到處出沒的社會市場下,雙非一本的小俱心感沒有任何優勢,苦苦找實習,實習要求雖說沒有秋招正式高,在苦苦投遞十幾大廠下,做測評、做筆試.....不知今年大廠對雙非學歷究竟如何評估,終于小俱迎來了美團、騰訊云智、游族的面試......每次面試后,小俱深知自己哪塊還沒有學到位,甚至有的問題沒有聽過,小俱最終進入人才池。雙非就真的菜吧......小俱仍不甘心,繼續沉淀......
最終小俱通過boss投遞小廠,甘心為公司做牛做馬,同時馬不停蹄的鞏固知識,通過二面,收到了北京一家實習offer,接著有重慶、成都。
小俱滿懷期待,興致勃勃去給輔導員請假!(劃重點!)
在輔導員要求提交幾種資料后
輔導員回復:我這里只能批準3天假期,你出去實習這件事必須和領導商量。
好,小俱等待批假......
過了一天,輔導員說:領導說他只能批7天假,有的課程還沒有完,你這每周需要回來一次,經過我們的開會,批準不同意。
啊!小俱說那我每周請假,每周回來,輔導員仍不同意!
小俱苦苦說機會來之不易,希望領導理解通融!
輔導員其實僅僅傳達了領導的命令,理智的小俱不麻煩年輕的輔導員,直接自己找領導。
于是小俱親自找到領導:?
領導:我這個只能批7天的假,根據目前的教學管理,不允許實習,再說,你實習地點離學校遠,每次請7天假也不現實,你這個就屬于請長假,你需要找大領導,他同意就行!
小俱人不罷休,去找大領導!
大領導:根據目前的教學管理規定,大三不允許實習............(此處省略各種理由,態度好,很委婉),我們非常支持你們實習,你們有這種意識也非常好,我很支持!(.....好,說了很多,就是不給假。。。)
最終小俱實習失敗。
小俱一級一級的找領導,最終失敗,但小俱調整心態,繼續沉淀。
現在大概理解了職責鏈模式了吧!
結構圖
實例
結構圖,舉例請假、加薪場景
管理者抽象類??Manager?
//管理者抽象類
abstract class Manager {protected String name;public Manager(String name) {this.name = name;}//設置管理者上級protected Manager superior;public void setSuperior(Manager superior){this.superior = superior;}//請求申請public abstract void requsetApplications(Request request);}
?申請Request類
//申請
class Request{//申請類別private String requestType;//申請內容private String requestContent;//數量private int number;public void setRequestType(String requestType) {this.requestType = requestType;}public void setRequestContent(String requestContent) {this.requestContent = requestContent;}public void setNumber(int number) {this.number = number;}public String getRequestType() {return requestType;}public String getRequestContent() {return requestContent;}public int getNumber() {return number;}
}
普通經理?CommonManager?
//普通經理
class CommonManager extends Manager{public CommonManager(String name) {super(name);}@Overridepublic void requsetApplications(Request request) {if (request.getRequestType()=="請假"&& request.getNumber()<=2){System.out.println(this.name+":"+request.getRequestContent()+"數量:"+ request.getNumber()+"天,批準");}else {if (this.superior!=null){this.superior.requsetApplications(request);}}}
}
?總監Director?
//總監
class Director extends Manager{public Director(String name) {super(name);}@Overridepublic void requsetApplications(Request request) {if (request.getRequestType()=="請假"&&request.getNumber()<=5){System.out.println(this.name+":"+request.getRequestContent()+"數量:" + request.getNumber()+"天,批準");}else {if (this.superior!=null){this.superior.requsetApplications(request);}}}
}
總經理GeneralManager??
//總經理 都會處理
class GeneralManager extends Manager{public GeneralManager(String name) {super(name);}@Overridepublic void requsetApplications(Request request) {if (request.getRequestType()=="請假"){System.out.println(this.name+":"+request.getRequestContent()+"數量:"+request.getNumber()+"天,批準");}else if (request.getRequestType()=="加薪"&&request.getNumber()<=5000){System.out.println(this.name+":"+request.getRequestContent()+"數量:"+request.getNumber()+"元,批準");}else if (request.getRequestType()=="加薪"&&request.getNumber()>5000){System.out.println(this.name+":"+request.getRequestContent()+"數量:"+request.getNumber()+"元,再說吧");}}
}
?客戶端:
class Test{public static void main(String[] args) {CommonManager manager = new CommonManager("經理");Director director = new Director("總監");GeneralManager generalManager = new GeneralManager("總經理");//設置每個級別的上級manager.setSuperior(director);director.setSuperior(generalManager);Request request = new Request();request.setRequestType("請假");request.setRequestContent("小菜請假");request.setNumber(1);manager.requsetApplications(request);Request request2 = new Request();request2.setRequestType("請假");request2.setRequestContent("小菜請假");request2.setNumber(4);manager.requsetApplications(request2);Request request3 = new Request();request3.setRequestType("加薪");request3.setRequestContent("小菜加薪");request3.setNumber(1000);manager.requsetApplications(request3);Request request4 = new Request();request4.setRequestType("加薪");request4.setRequestContent("小菜加薪");request4.setNumber(6000);manager.requsetApplications(request4);}
}
?運行結果
職責鏈模式優點
「降低了對象之間的耦合度」
責任鏈模式讓發送者不需要知道對方的具體是哪個處理者處理請求。
「增強了系統的可擴展性」
可以根據需要增加新的請求處理類,滿足開閉原則。
「增強了給對象指派職責的靈活性」
當工作流程發生變化,客戶端可以動態地改變鏈內的成員或者調動它們的次序,也可動態地新增或者刪除責任。
「責任鏈簡化了對象之間的連接」
每個對象只需保持一個指向其后繼者的引用。
「責任分擔」
每個類只需要處理自己該處理的工作,不該處理的傳遞給下一個對象完成。
職責鏈模式缺點
- 不能保證每個請求一定被處理。由于一個「請求沒有明確的接收者」,該請求可能一直傳到鏈的末端都得不到處理。
- 當責任鏈比較長的時候,請求的處理可能涉及多個處理對象,系統性能受影響。
- 職責鏈建立的合理性要靠客戶端來保證,增加了客戶端的復雜性,可能會造成循環調用。
使用場景
1.springmvc流程
就拿這個springMvc的執行流程來說,全部流程就組成了一個鏈條。每一個步驟就是一個結點,每個結點都會有對應的處理方法,每個結點處理完成之后,就會進入下一個結點。一旦某個結點出現異常,那么當前的鏈路就會停止,當前請求中斷。
2.mybatis的執行流程
mybatis的執行流程也是通過這個責任鏈模式,如首先會創建這個SqlSessionFactory,然后通過這個工廠創建一個SqlSession,這個SqlSession只是一個門面模式,會通過Executer執行增刪改查的操作,然后一個Handler用于設置參數,一個Handler用于返回結果集,最后通過這個StatementHandler將執行結果獲取。里面的整個步驟就相當于形成了一個鏈條,執行完當前結點就會進入下一個結點,如果出現異常,鏈條終止往下執行。
3.spring的過濾器和攔截器
spring里面的這個過濾器鏈路的調用,以及攔截器的鏈路調用,也是采用這種責任鏈模式
?
?
參考文章:http://t.csdnimg.cn/rkTNL
?