設計模式總結之行為型模式


行為型模式設計到算法和對象間的職責分配,不僅描述對象或類的模式,還描述它們之間的通信方式,刻划了運行時難以跟蹤的復雜的控制流,它們將你的注意力從控制流轉移到對象間的關系上來。行為型類模式采用繼承機制在類間分派行為,例如Template Method 和Interpreter;行為對象模式使用對象復合而不是繼承。一些行為對象模式描述了一組相互對等的對象如何相互協作以完成其中任何一個對象都單獨無法完成的任務,如Mediator、Chain of Responsibility、Strategy;其它的行為對象模式常將行為封裝封裝在一個對象中,並將請求指派給它。

常見行為型模式有11種:CCIIMM(Chain of Responsibility職責鏈、Command命令、Interpreter解釋器、Iterator迭代、Mediator中介者、Memento備忘錄),OSSTV(Observer觀察者、State狀態、Strategy策略、Template Method模版方法、Visitor訪問者)。

  1. 職責鏈模式(Chain of Responsibility):將對象連成一條鏈,並沿着這條鏈傳遞請求,直到有一個對象處理它為止。使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。職責鏈可簡化對象的相互連接,它們僅需保持一個指向后繼者的引用,而不需要保持所有候選者的引用,鏈中對象不用知道鏈的結構,接受者和發送者都沒有對方的明確信息。可以通過在運行時刻動態的增加或修改鏈來動態的改變處理一個請求的職責;不能保證請求一定被接受,一個請求也可能因鏈沒有被正確配置而得不到處理。

    參與者:

    (1)Handler:定義一個實現請求的接口。

    (2)ConcreteHandler:處理它負責的請求,可訪問它的后繼者;如果可處理請求就處理,否則將請求轉發給它的后后繼者。

    (3)Client:向鏈上的具體處理者對象提交請求。

    協作:當客戶提交一個請求時,請求沿着鏈傳遞直至有一個ConcreteHandler對象負責處理它或者到鏈末。

     

  2. 命令模式(Command):將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。別名動作(Action),事務(Transaction)。和很多設計模式一樣,命令模式在你的請求和處理之間加上了一個中間人的角色,來達到分離耦合的目的。

    參與者:

    (1):命令角色(Command):聲明執行操作的接口。

    (2)具體命令角色(ConcreteCommand):講一個接受者對象綁定一個動作;調用接收者相應的操作,以實現命令角色聲明的執行操作的接口。

    (3)客戶角色(Client): 創建一個具體命令對象(並可以設定它的接收者)。

    (4)請求者角色(Invoker):調用命令對象執行請求。

    (5)接收者角色(Receiver):知道如何實施與執行一個請求相關的操作。任何類都可能做一個接收者。

    協作:Client創建一個具體的ConcreteCommand對象並指定它的Receiver對象;某Invoker對象存儲該ConcreteCommand對象,通過調用Command對象的Execute操作來提交一個請求,若該命令是可撤銷的,ConcreteCommand就在執行Execute操作之前存儲當前狀態以用於取消該命令;ConcreteCommand對象調用它的Receiver的一些操作以執行該請求。

    總結:命令模式將調用操作的請求對象和知道如何實現操作的接受對象解耦;具體命令角色可被不同的請求者角色重用,它可將多個命令裝配成一個復合命令,增加新的具體命令角色無需改變已有的類。Gof總結命令模式適用以下情況:(1)需要抽象出待執行的動作,然后以參數的形式提供出來(類似於過程設計中的回調機制),命令模式正是回調機制的一個面向對象的替代品。(2)在不同的時刻指定、排列和執行請求。一個命令對象可以有與初始請求無關的生存期。(3)需要支持取消操作(4)支持修改日志功能,支持事務操作。從面向對象角度看命令模式是不完美的,命令角色僅僅包含一個方法,是將函數層的角色提升到了類的層面,但命令模式很成功的解決了很多問題,遍布在Struts中。

  3. 解釋器模式(Interpreter):定義語言(使用規定格式和語法的代碼)的文法,並且建立一個解釋器來解釋該語言中的句子。它屬於類行為模式。解釋器模式提供一種簡單方法來執行語法且容易修改和擴展。一般系統中很多類使用相似的語法,可以使用一個解釋器來代替每一個規則實現一個解釋器。在解釋器中不同規則是由不同類實現的,從而使添加一個新的語法規則簡單化,但對於復雜語法難以維護。

4.迭代器模式(Iterator):提供一種方法順序訪問一個集合中各個元素,而又不暴露該對象的內部表示。別名:游標(Cursor)。

5.中介者模式(Mediator):用一個中介對象封裝一系列的對象交互。中介者使各對象間不需要顯式的相互引用,從而使其松散耦合,而起可以獨立的改變它們之間的交互。

參與者:

(1)Mediator(中介者):定義一個接口用於和同事對象間通信。

(2)ConcreteMediator(具體中介者):協調各同事對象對象實現協作行為;了解並維護它的各個同事。

(3)Colleague(同事角色):每一個同事角色都知道它的中介者對象,在需要與其它同事通信時,與它的中介者通信。

協作:同事向一個中介者發送和接收請求。中介者在各同事間適當的轉發請求以實現協作行為。

總結:廣泛應用的MVC也算是中介者模式在框架設計中的一個應用(控制層是位於表現層和模型層之間的中介者)。中介者模式在結構上和觀察者模式、命令模式相似,而應用目的與外觀模式相似。在結構上,中介者模式與觀察者模式和命令模式都添加了中介對象——只是中介模式去掉了后兩者行為上的方向。但觀察者模式中的觀察者、命令模式中的命令都是被客戶所知的,具體哪個觀察者、應用都是由客戶來指定的,而大多中介者角色對客戶是透明的,造成這種區別的原因是它們要達到的目的不同。從目的上看,命令模式與外觀模式相似;但外觀模式是介於客戶程序與子系統之間的,而中介者模式是介於子系統與子系統之間的;前者將復雜的邏輯提取出一個統一的接口,簡化客戶對邏輯的使用,而后者的加入並沒有改變客戶原有的使用習慣,它是隱藏在原有邏輯后面的,使得代碼邏輯更加清晰可用。中介者模式最大的好處是將同事角色解耦,簡化原有系統的通信協議——將原有的多對多變為一對多,提高了代碼的可復用性。在使用中介者模式時要注意控制中介者角色的大小。

6.備忘錄模式(Memento):在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,以后可將該對象恢復到原先保存的狀態。別名:Token。

參與者:

(1)Memento(備忘錄角色):存儲備忘發起角色的內部狀態,備忘發起角色根據需要決定備忘錄角色存儲自己哪些內部狀態。為了防止備忘發起角色以往的對象訪問備忘錄,管理者只能看到備忘錄的窄接口——它只能把備忘錄傳遞給其它對象,原備忘發起角色可以看到一個寬接口,允許它訪問返回到先前狀態所需的所有數據。

(2)Originator(原發器,備忘發起角色):創建一個備忘錄,用於記錄當前時刻它的內部狀態,在需要時使用備忘錄恢復內部狀態。

(3)Caretaker(管理器,備忘錄管理者角色):負責管理備忘錄,不能對備忘錄的內容進行操作或檢查。

協作:管理器向原發器請求一個備忘錄,保留一段時間后將其返回給原發器。備忘錄是被動的,只有創建備忘錄的原發器會對它的狀態進行賦值和檢索。

7.觀察者模式(Observer):定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴它的對象都得到通知並自動更新。別名:Dependents(依賴),發布-訂閱(Publish-subscribe)。

參與者:

(1)Subject(抽象目標角色):提供注冊和刪除觀察者對象的接口,知道它的觀察者。可以有任意多個觀察者觀察同一個目標。

(2)Observer(觀察者角色):為那些在目標發生改變時需要更新的對象定義一個更新接口。

(3)ConcreteSubject(具體目標):將有關狀態存入ConcreteObserver對象,當它的狀態發生改變時,向它的各個觀察者發出通知。

(4)ConcreteObserver(具體觀察者):維護一個指向ConcreteSubject對象的引用,存儲有關狀態,這些狀態應與目標狀態保持一致,實現Observer的更新接口,以使自己狀態與目標狀態保持一致。

協作:當ConcreteSubject發生任何可能導致其觀察者與其本身狀態不一致的改變時,它將通知各個觀察者。在得到一個具體目標的改變通知后,ConcreteObserver可向目標對象查詢信息,從而使它的狀態與目標對象狀態保持一致。

8狀態模式(State):允許一個對象在其內部狀態改變時改變它的行為,對象看起來似乎修改了它的類。別名:狀態對象。

參與者:

(1)Context(環境):維護一個ConcreteState實例,這個實例定義當前狀態。

(2)State(狀態):定義一個接口以封裝與Context的一個特定狀態相關的行為。

(3)ConcreteState(具體狀態):實現一個與Context的一個狀態相關的行為。

協作:Context將與狀態相關的請求委托給當前的ConcreteState對象處理,也可將自身作為一個參數傳遞傳遞給以處理該請求的狀態對象,從而使狀態對象在必要時可訪問Context。Context是客戶使用的主要接口,客戶可用狀態對象來配置一個Context,一旦Context配置完畢,它的客戶不再需要直接與狀態對象打交道。Context和ConcreteState子類都可決定哪個狀態時另外哪一個狀態的后繼者,以及在何種條件下進行狀態轉換。

9.策略模式(Strategy):定義一系列算法,把它們一個個封裝起來,並且使它們可相互替換,本模式使得算法可獨立於使用它的客戶而變化。別名:政策(policy)。

參與者:(1)Strategy(策略):定義所有支持算法的公共接口。Context使用這個接口來調用某個Concretestrategy定義的算法。

(2)ConcreteStrategy(具體策略):以Strategy為接口實現某具體算法。

(3)Context(上下文):維護一個Strategy對象的引用,用一個ConcreteStrategy來配置,可定義一個接口來讓Strategy訪問它的書籍。

協作:Strategy和Context相互作用以實現選定的算法。當算法被調用時,Context可將該算法所需要的所有數據都傳遞給Strategy,或者Context可將自身作為一個參數傳遞給Strategy操作,從而使Strategy在需要時可以回調Context。Context將它的客戶請求轉發給它的Strategy,客戶通常創建並傳遞一個ConcreteStrategy對象給該Context;這樣客戶僅與Context交互。通常有一系列ConcreteStrategy類可供客戶從中選擇。

State對比Strategy:Strategy模式和State模式在結構上非常相似,但在概念上它們間的目的差異非常大。區分這兩個模式的關鍵是看行為是由狀態驅動還是由一組算法驅動,通常State模式的狀態時在對象內部的,Strategy模式的策略可在對象外部,即這兩個模式的區分就在於使用的目的不同——策略模式用來處理算法變化,而狀態模式則是處理狀態變化。算法是否變化完全是由客戶程序決定的,而且往往一次只能選擇一種算法,不存在算法中途變化的情況。而狀態模式如定義中所言,在它的生命周期中存在着狀態的轉變和行為的更改,而且狀態變化是一個線性的整體;對客戶而言,這種狀態的變化往往是透明的。

10.模版方法模式(Template Method):定義一個操作中算法的骨架,而將一些步驟延遲到子類中,使得子類可以不改變算法的結構即可重定義該算法的某些特定的步驟。模版方法是一種基本代碼復用技術,在類庫中尤為重要,它們提取了類庫中的公共行為。算法的結構可理解為根據需求設計出來的業務流程,特定的步驟就是指那些可能在內容上存在變數的環節。

參與者:(1)AbstractClass(抽象類):定義一個模版方法,定義一個算法的骨架;定義抽象的原語操作,具體的子類將重定義它們以實現算法的各個步驟。該模版方法不僅調用原語操作,也調用定義在AbstractClass或其它對象中的操作。

(2)ConcreteClass(具體類)實現原語操作以完成算法中子類相關的特定步驟。

協作:ConcreteClass靠AbstractClass來實現算法中不變的步驟。

實例:Junit。

適用情況:(1):一次性實現算法的不變的部分,並將可變的行為留給子類來實現。

(2):各子類中公共的行為應該被提取出來並集中到一個公共父類中以避免代碼重復。

(3):控制子類擴展。

11.訪問者模式(Visitor):表示以作用於對象結構中各元素的操作,它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。

參與者:(1)Visitor(訪問者):為該對象結構中每一個ConcreteElement聲明一個Visit操作,該操作的名稱和特征標志了發送Visit請求給該標識者的那個類,使訪問者可以確定正被訪問元素的具體的類。這樣訪問者就可以通過該元素的特定接口直接訪問它。

(2)ConcreteVisitor(具體訪問者):實現每個Visitor聲明的操作。每個操作實現本算法的一部分,而該算法片段乃是對應於結構中對象的類。ConcreteVisitor為該算法提供了上下文並存儲它的局部狀態,這一狀態常常在遍歷該結構的過程中累積結果。

(3)Element(元素):定義一個Accept操作,它以一個訪問者為參數。

(4)ConcreteElement(具體元素):實現Accept操作,該操作以一個訪問者為參數。

(5)ObjectStructure(對象結構):可以是一個復合,提供一個高層接口以允許訪問者訪問它的元素,能枚舉它的元素。

協作:一個使用Visitor模式的客戶必須創建一個ConcreteVisitor對象,然后遍歷該對象結構,並用該訪問者訪問每一個元素。當一個元素被訪問時它調用對應它的類的Visitor操作,如有必要該元素將自身作為操作的一個參數以便該訪問者訪問它的狀態。

 

總結:行為模式涉及到算法和對象職責間的分配,行為類模式采用繼承機制在類間分派行為,Template Method和Interpreter是類行為模式。行為對象模式使用對象復合而不是繼承,一些行為對象模式描述了一組相互對等的對象如何相互協作以完成其中任何一個對象都單獨無法完成的任務,如Mediator在對象間引入一個mediator對象提供了松耦合所需的間接性;Chain of Responsibility提供了更松的耦合,它通過一條候選對象鏈隱式的向一個對象發松請求,可以運行時刻決定哪些候選者參與到鏈中;Observer定義並保持了對象間的依賴關系;其它的行為對象模式常將行為封裝封裝在一個對象中,並將請求指派給它,Strategy模式將算法封裝在對象中,這樣可以方面的改變和指定一個對象所使用的算法;Command模式將請求封裝在對象中,這樣它就可以作為參數來傳遞,已可以存儲在歷史列表中或以其它方式使用;State模式封裝一個對象的狀態,使得當這個對象的狀態對象變化時,該對象可改變它的行為;Visitor模式封裝分布於多個類之間的行為;而Iterator模式則抽象了訪問和遍歷一個集合中對象的方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM