職責鏈
1.概述
? ? ? ?你去政府部門求人辦事過嗎?有時候你會遇到過官員踢球推責,你的問題在我這里能解決就解決,不能解決就推卸給另外個一個部門(對象)。至于到底誰來解決這個問題呢?政府部門就是為了可以避免屁民的請求與官員之間耦合在一起,讓多個(部門)對象都有可能接收請求,將這些(部門)對象連接成一條鏈,并且沿著這條鏈傳遞請求,直到有(部門)對象處理它為止。
例子1:js的事件浮升機制
例子2:
2.問題
如果有多個對象都有可能接受請求,如何避免避免請求發送者與接收者耦合在一起呢?
3.解決方案
職責鏈模式(Chain of Responsibility):使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。(Avoid coupling the sender of a request to itsreceiver by giving morethan one objecta chance to handle the request.Chain the receiving objects andpassthe request along the chain until an object handles it.?)
1)在職責鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。2)請求在這條鏈上傳遞,直到鏈上的某一個對象處理此請求為止。3)發出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。
4.適用性
在以下條件下使用Responsibility 鏈:
? 有多個的對象可以處理一個請求,哪個對象處理該請求運行時刻自動確定。
? 你想在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。
?可動態指定一組對象處理請求。
5.結構
一個典型的對象結構可能如下圖所示:
6. 模式的組成
抽象處理者角色(Handler:Approver):定義一個處理請求的接口,和一個后繼連接(可選)
具體處理者角色(ConcreteHandler:President):處理它所負責的請求,可以訪問后繼者,如果可以處理請求則處理,否則將該請求轉給他的后繼者。
客戶類(Client):向一個鏈上的具體處理者ConcreteHandler對象提交請求。
7. 效果
Responsibility 鏈有下列優點和缺點( l i a b i l i t i e s ) :
職責鏈模式的優點:
1 ) 降低耦合度 :該模式使得一個對象無需知道是其他哪一個對象處理其請求。對象僅需知道該請求會被“正確”地處理。接收者和發送者都沒有對方的明確的信息,且鏈中的對象不需知道鏈的結構。
2)?職責鏈可簡化對象的相互連接?: ? ?結果是,職責鏈可簡化對象的相互連接。它們僅需保持一個指向其后繼者的引用,而不需保持它所有的候選接受者的引用。
3) 增強了給對象指派職責( R e s p o n s i b i l i t y )的靈活性?:當在對象中分派職責時,職責鏈給你更多的靈活性。你可以通過在運行時刻對該鏈進行動態的增加或修改來增加或改變處理一個請求的那些職責。你可以將這種機制與靜態的特例化處理對象的繼承機制結合起來使用。
4)增加新的請求處理類很方便
職責鏈模式的缺點:1) ??不能保證請求一定被接收。既然一個請求沒有明確的接收者,那么就不能保證它一定會被處理 —該請求可能一直到鏈的末端都得不到處理。一個請求也可能因該鏈沒有被正確配置而得不到處理。2) ??系統性能將受到一定影響,而且在進行代碼調試時不太方便;可能會造成循環調用。
8. 純與不純的職責鏈模式
純的職責鏈模式:一個具體處理者角色處理只能對請求作出兩種行為中的一個:一個是自己處理(承擔責任),另一個是把責任推給下家。不允許出現某一個具體處理者對象在承擔了一部分責任后又將責任向下傳的情況。請求在責任鏈中必須被處理,不能出現無果而終的結局。反之就是不純的職責鏈模式。??在一個純的職責鏈模式里面,一個請求必須被某一個處理者對象所接收;在一個不純的職責鏈模式里面,一個請求可以最終不被任何接收端對象所接收。
9.實現
我們先來看不純的職責模式:
假如在公司里,
如果你的請假時間小于0.5天,那么只需要向leader打聲招呼就OK了。
如果0.5<請假天數<=3天,需要先leader打聲招呼,要不然leader不知你跑哪里,然后部門經理直接簽字。
如果3<請假天數 天,需要先leader打聲招呼,然后到部門經理簽字,最好總經經理確認簽字,當你看到這情況后你心里是不是已經有了自己的想法了?寫一系列的if語句來一條條的判斷.但這樣的寫法雖然可以實現目前的需求,可如果當流程改了呢?我請假超過3天,告訴leader和總經理簽字就可以,那你又得一步一步修改程序。如果if語句的條數發生變化的話我們還必須在代碼中添加必要的if判斷,這對于程序的維護來說是相當麻煩的.如果我們使用職責鏈模式的話就可以相當簡單了.
命令模式
目的:
任何模式的出現,都是為了解決一些特定的場景的耦合問題,以達到對修改封閉,對擴展開放的效果。命令模式也不例外:
命令模式是為了解決命令的請求者和命令的實現者之間的耦合關系。
解決了這種耦合的好處我認為主要有兩點:
1.更方便的對命令進行擴展(注意:這不是主要的優勢,后面會提到)
2.對多個命令的統一控制(這種控制包括但不限于:隊列、撤銷/恢復、記錄日志等等)
模式解析:
經典的命令模式包括4個角色:
Command:定義命令的統一接口
ConcreteCommand:Command接口的實現者,用來執行具體的命令,某些情況下可以直接用來充當Receiver。
Receiver:命令的實際執行者
Invoker:命令的請求者,是命令模式中最重要的角色。這個角色用來對各個命令進行控制
訪問器
訪問者模式就是表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。?
類圖和樣例:
抽象訪問者(Visitor)角色:聲明了一個或者多個訪問操作,形成所有的具體元素角色必須實現的接口。
具體訪問者(ConcreteVisitor)角色:實現抽象訪問者角色所聲明的接口,也就是抽象訪問者所聲明的各個訪問操作。
抽象節點(Element)角色:聲明一個接受操作,接受一個訪問者對象作為一個參量。
具體節點(ConcreteElement)角色:實現了抽象元素所規定的接受操作。
結構對象(ObiectStructure)角色:有如下的一些責任,可以遍歷結構中的所有元素;如果需要,提供一個高層次的接口讓訪問者對象可以訪問每一個元素;如果需要,可以設計成一個復合對象或者一個聚集,如列(List)或集合(Set)。?
解析器
意圖:
給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子.
適用性:
1、當有一個語言需要解釋執行,并且你可以把該語言中的句子表示為一個抽象的語法樹時,可使用解釋器模式.而當存在以下情況時,該模式的效果最好:
2、該文法簡單,對于復雜的文法,文法的類層次變得龐大而無法管理.此時,語法分析程序生成器這樣得工具時更好得選擇。它們無需構建抽象語法樹即可解釋表達式,這樣可以節省空間而且還可以節省時間;
3、效率不是一個關鍵的問題,最高效的解釋器通常不是通過直接解釋語法分析樹實現的,而是首先把他們轉換成另外一種形式.例如:正則表達式通常被轉換成狀態機。但即使在這種情況下,轉換器仍可用解釋器模式實現,該模式仍是有用的.
結構圖:
Interpreter設計模式中的幾種角色:
AbstractExpression:
-?聲明一個抽象的Interpret方法,抽象語法樹中所有的節點都必須實現該抽象方法。
TerminalExpression:
-?實現和語法中末端符號相關的Interpret方法。
-?在每個句子的末端符號中均需要一個TerminalExpression實例。
NonterminalExpression:
另外一個實現了AbstractExpression?接口的類,用來處理語法樹中非末端節點的語法。它含有下一個AbstractExpression(s)的引用,調用它每個子節點的Interpret方法。
Context:
Interpreter方法所需要的信息的容器,該信息對Interpreter而言全局可見。充當幾個AbstractExpresssion?實例之間的通訊頻道。
PatternClient:
構建或者接收一個抽象語法書的實例。對于一個特定的句子而言,語法樹往往由若干個TerminalExpressions?和NonterminalExpression組成。PatterClient在合適的context下,調用Interpret方法。
Interpreter模式的應用場合是interpreter模式應用中的難點,只有滿足“業務規則頻繁變化,且類似的模式不斷重復出現,并且容易抽象為語法規則的問題”才適合使用Interpreter模式。
使用Interpreter模式來表示文法規則,從而可以使用面向對象技巧來方便地“擴展”文法。
Interpreter模式比較適合簡單的文法表示,對于復雜的文法表示,Interpreter模式會產生比較大的類層次結構,這時候就不應該采用Interpreter模式了。
效率不是一個Interpreter關心的關鍵問題。最高效的解釋器通常不是通過直接解釋語法分析樹實現的,而是首先將它們轉換成另一種形式。例如:正則表達式通常被轉換成狀態機。但即使在這種情況下,如果效率不是一個關鍵問題,轉換器仍可用Interpreter模式實現,該模式仍是有用的。