设计模式学习(五):行为型模式
行為模式涉及到算法和對(duì)象間職責(zé)的分配。行為模式不僅描述對(duì)象或類的模式,還描述它們之間的通信模式。這些模式刻畫了在運(yùn)行時(shí)難以跟蹤的復(fù)雜的控制流。它們將你的注意力從控制流轉(zhuǎn)移到對(duì)象間的聯(lián)系方式上。
行為型模式的三個(gè)典型特點(diǎn):
封裝變化
對(duì)象作為參數(shù)
對(duì)發(fā)送者和接收者解耦
Chain of Responsibility
意圖:為解除請(qǐng)求的發(fā)送者和接收者之間耦合,而使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它。
動(dòng)機(jī): 解除請(qǐng)求的發(fā)送者和接收者之間耦合,在對(duì)象間傳遞待處理的請(qǐng)求。
適用性:用于請(qǐng)求的跨層傳遞,解除請(qǐng)求發(fā)送者和請(qǐng)求的最終處理者之間的耦合。統(tǒng)一地處理客戶請(qǐng)求。常用于窗口系統(tǒng),處理鼠標(biāo)或鍵盤事件,典型應(yīng)用:wxWidget的事件系統(tǒng)。
結(jié)構(gòu): 客戶請(qǐng)求一般采用Command封裝,使易于傳遞。一般不同對(duì)象采用統(tǒng)一的接口來處理請(qǐng)求。如果請(qǐng)求處理者對(duì)象存放在列表中,一般要求使用繼承實(shí)現(xiàn)。
優(yōu)點(diǎn): 易于請(qǐng)求的跨層傳遞;解除對(duì)象耦合(封裝請(qǐng)求的真實(shí)處理者);統(tǒng)一請(qǐng)求處理(封裝請(qǐng)求的變化)。
組合模式: 經(jīng)常采用Command來封裝不同類型的請(qǐng)求.
Command
意圖:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化(傳遞請(qǐng)求);對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可取消的操作。
動(dòng)機(jī): 封裝請(qǐng)求的類型;讓請(qǐng)求具有對(duì)象的特性(具有狀態(tài)的實(shí)體),這樣就可以傳遞、保存或者采用不同的方式來處理請(qǐng)求對(duì)象。
結(jié)構(gòu): 用繼承來封裝請(qǐng)求的類型;除了不一樣的構(gòu)造和初始化函數(shù)外,提供一致的核心接口。
優(yōu)點(diǎn): 讓請(qǐng)求具有對(duì)象的特性,使客戶能夠采用不同的方式來處理請(qǐng)求對(duì)象,比如可以解除對(duì)象構(gòu)造和對(duì)象使用的耦合,即實(shí)體解耦和時(shí)間解耦。
用途: 經(jīng)常用于數(shù)據(jù)庫(kù)事務(wù)操作,設(shè)備控制,多線程核心(Active Object)以及GUI的do/undo管理等。或者用于消除過多的條件分派。
組合模式: 經(jīng)常用于Chain ofResponsibility中的請(qǐng)求封裝;經(jīng)常和Composite組合使用,提供統(tǒng)一的對(duì)待Command的途徑,封裝“一對(duì)多”的關(guān)系。
Iterator
意圖:提供一種方法順序訪問一個(gè)聚合對(duì)象中各個(gè)元素, 而又不需暴露該對(duì)象的內(nèi)部表示。
動(dòng)機(jī): 封裝對(duì)對(duì)象的訪問規(guī)則或者算法。本質(zhì):提供一致的遍歷接口
適用性: 適用于為多個(gè)不同聚合類提供一致的遍歷接口。
結(jié)構(gòu):抽象迭代器提供類似hasNext(),Next(), Remove()等接口,并由具體聚合類通過createIterator()創(chuàng)建具體的迭代器。
優(yōu)點(diǎn): 封裝聚合類內(nèi)部實(shí)現(xiàn),提供一致對(duì)外接口
Interpreter
意圖:給定一個(gè)語言, 定義它的文法的一種表示,并定義一個(gè)解釋器, 該解釋器使用自身定義表示來解釋語言中的句子。
動(dòng)機(jī): 采用不同的對(duì)象來表示不同的文法,使文法易于組合使用。提供一種可選擇的方式,將易變的組合邏輯推給客戶代碼。
結(jié)構(gòu):將每一個(gè)語法規(guī)則表示成一個(gè)類,方便于實(shí)現(xiàn)語言。
適用性:方便實(shí)現(xiàn)簡(jiǎn)單語言的解釋器(常用yacc和lex工具來編寫語言的解釋器原型)
Mediator
意圖:用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互。中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可獨(dú)立地改變它們之間的交互。
動(dòng)機(jī): 封裝多個(gè)對(duì)象間的交互關(guān)系,解除耦合。
適用性: 適用于多個(gè)對(duì)象交互關(guān)系復(fù)雜且易變的情況。常用于協(xié)調(diào)GUI組件。
結(jié)構(gòu): 提供一個(gè)幕后類來統(tǒng)一管理不同對(duì)象間的交互關(guān)系。
優(yōu)點(diǎn): 封裝多個(gè)對(duì)象間的交互關(guān)系,使客戶更加容易編程。
Memento
意圖:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣以后就可將該對(duì)象恢復(fù)到保存的狀態(tài)。
動(dòng)機(jī): 保存對(duì)象狀態(tài),用于對(duì)象狀態(tài)的回滾或重新構(gòu)造。
適用性: 用于對(duì)象內(nèi)部狀態(tài)易變,且對(duì)象狀態(tài)具有某種價(jià)值的場(chǎng)合。
結(jié)構(gòu): 使用簡(jiǎn)單的結(jié)構(gòu)體即可完成任務(wù)。
優(yōu)點(diǎn): 提供保存對(duì)象的另一種選擇。
缺點(diǎn):存儲(chǔ)耗時(shí),常用語言自帶的序列化(serialization)機(jī)制存儲(chǔ)系統(tǒng)狀態(tài)。
Observer
意圖:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,以便當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)刷新。
動(dòng)機(jī): 封裝對(duì)象間一對(duì)多的依賴關(guān)系,提供統(tǒng)一的管理點(diǎn)。
適用性: 所有具有一對(duì)多依賴關(guān)系且需要傳遞狀態(tài)信息的對(duì)象管理。
結(jié)構(gòu): 使用雙抽象結(jié)構(gòu)(主題和觀察者),一個(gè)抽象管理主題狀態(tài)的通知行為(簡(jiǎn)化主題派生類的行為),一個(gè)抽象用于封裝不同的狀態(tài)觀察者。
優(yōu)點(diǎn): 在具有多個(gè)觀察者時(shí),可簡(jiǎn)化狀態(tài)通知部分的Hard-coding,并且易于擴(kuò)展。
變化: 在狀態(tài)比較復(fù)雜的情況下,一般采用某種約定的參數(shù)來提示觀察者狀態(tài)發(fā)生了什么樣的變化,簡(jiǎn)化對(duì)象更新過程。
State
意圖:允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為(外部行為)。對(duì)象看起來似乎修改了它所屬的類。
動(dòng)機(jī): 分離狀態(tài)機(jī)的邏輯和動(dòng)作;或者是分離狀態(tài)和行為(動(dòng)作)。
結(jié)構(gòu):state定義所用具體狀態(tài)的共同接口(事件接口);任何具體狀態(tài)實(shí)現(xiàn)該相同接口。Context擁有所有狀態(tài)對(duì)象。根據(jù)不同事件,context在不同狀態(tài)對(duì)象中切換,從而改變自身行為。
優(yōu)點(diǎn):避免用戶直接和狀態(tài)交互;去除掉大量的條件語句;使系統(tǒng)更加易于擴(kuò)展和維護(hù)。
變化:1)一般來講,當(dāng)狀態(tài)改變是固定的,狀態(tài)轉(zhuǎn)換邏輯適合放在Context中;當(dāng)轉(zhuǎn)換更動(dòng)態(tài)的時(shí)候,通常將狀態(tài)轉(zhuǎn)換邏輯放在State中,但這會(huì)使?fàn)顟B(tài)類之間產(chǎn)生依賴。總之,該決策決定了究竟哪個(gè)類是對(duì)修改封閉的(context或state)。2)如有多個(gè)Context,則可考慮共享所有的狀態(tài)類。
補(bǔ)充:有限狀態(tài)自動(dòng)機(jī)(FSM)
有限狀態(tài)自動(dòng)機(jī)的兩種表示方式: 狀態(tài)遷移圖(STD)和狀態(tài)遷移表(STT)
狀態(tài)遷移圖(STD)至少由4部分組成。圓形表示狀態(tài);連接狀態(tài)的箭頭被稱為遷移;遷移被用一個(gè)后面跟著動(dòng)作名的時(shí)間做了標(biāo)記,組成事件/動(dòng)作對(duì)。類似數(shù)字電子中的狀態(tài)轉(zhuǎn)移圖,本質(zhì)上就是一個(gè)東西。
狀態(tài)遷移表(STT)用一個(gè)表的形式來描述系統(tǒng)中狀態(tài)的轉(zhuǎn)移。表中的每一列表示一個(gè)狀態(tài)遷移的完整過程。由下面4個(gè)部分組成一列:
起始狀態(tài)??觸發(fā)遷移的事件? 終止?fàn)顟B(tài)?? 所執(zhí)行的動(dòng)作
使用狀態(tài)遷移圖(STD)和狀態(tài)遷移表(STT)來描述自動(dòng)狀態(tài)機(jī)是非常有效的,并且非常容易檢測(cè)那么未知的以及沒有處理的狀態(tài)轉(zhuǎn)移情況。這對(duì)編程是很有幫助的,因?yàn)樵趯?shí)際編碼中,非常容易遺漏非正常的狀態(tài)轉(zhuǎn)移,而這些遺漏往往是錯(cuò)誤的根源。
實(shí)現(xiàn)有限狀態(tài)自動(dòng)機(jī)(FSM)的技術(shù):
嵌套的switch/case語句,解釋遷移表和State模式。
在簡(jiǎn)單其狀態(tài)遷移中,使用嵌套的switch/case語句就足夠的。在復(fù)雜情況下,使用State模式比較好。解釋遷移表也容易實(shí)現(xiàn),但不是這里討論的目標(biāo),最主要的就是表的查找。
State的標(biāo)準(zhǔn)結(jié)構(gòu)圖:
State模式徹底的分離了狀態(tài)機(jī)的邏輯和動(dòng)作。動(dòng)作是在Context類中實(shí)現(xiàn)的,而邏輯則是分布在State類的派生類中。這使得二者可以非常容易的獨(dú)立變化,互補(bǔ)影響。例如,只要使用State的另一個(gè)派生類。就可以非常容易地在一個(gè)不同的狀態(tài)邏輯中重用Context類的動(dòng)作。此外,我們也可以在不影響State派生類邏輯的情況下創(chuàng)建Context的派生類來更改或者替換動(dòng)作的實(shí)現(xiàn)。
可以使用狀態(tài)機(jī)的地方:作為GUI中高層應(yīng)用策略;GUI交互控制器;分布式處理等。幾乎凡有狀態(tài)存在的地方均可以考慮采用有限狀態(tài)機(jī)。
Strategy
意圖:定義一系列的算法,把它們一個(gè)個(gè)封裝起來, 并且使它們可相互替換。該模式使得算法的變化可獨(dú)立于使用它的客戶。
動(dòng)機(jī): 封裝不同的算法。定制一組可以互換的算法族。
適用性: 同一個(gè)問題存在多種不同的解決方案。
結(jié)構(gòu): 為了滿足算法之間的互換性,必須使用繼承,并且遵循Liskov原則。
優(yōu)點(diǎn): 封裝算法的變化。
組合模式: 經(jīng)常在使用算法的基類Context中使用Template Method。如果Context的派生類中要求所使用的算法動(dòng)態(tài)改變,還常常把Factory Method內(nèi)嵌到派生類中來創(chuàng)建不同的算法類。
區(qū)別:策略模式和狀態(tài)模式具有相同類圖。策略模式是圍繞可互換的算法來創(chuàng)建業(yè)務(wù)的,由Client自行決定具體策略。狀態(tài)模式則通過改變對(duì)象內(nèi)部狀態(tài)幫助對(duì)象控制自己的行為。
Template Method
意圖:定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
動(dòng)機(jī): 消除子類中的重復(fù)代碼,簡(jiǎn)化子類代碼。
適用性: 當(dāng)各個(gè)子類中,混雜著不變和可變的行為時(shí),就可以使用該模式。將不變的行為放入父類中,子類只需定制可變的行為。這里不變還包括行為的執(zhí)行順序。
結(jié)構(gòu): 必須使用繼承關(guān)系。
優(yōu)點(diǎn): 消除子類的重復(fù)行為。
組合模式: 經(jīng)常和FactoryMethod、Strategy一起使用。在分解不變和可變行為時(shí),還常可借助組合方法(ComposeMethod)和Collecting Parameter模式。
Visitor
意圖:表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
動(dòng)機(jī): 在不改變?cè)?一般是特定的數(shù)據(jù)結(jié)構(gòu))的情況下,增加新的功能接口。
適用性: 原有的類結(jié)構(gòu)不能或者不容易改變;或者新加的功能不屬于原類的職責(zé)范疇。
結(jié)構(gòu): 雙重分派。增加一個(gè)Visitor類,并針對(duì)所有要訪問的派生類增加單獨(dú)的訪問接口(在Visitor中)。本質(zhì)上,Visitor模式中的兩次分派形成一個(gè)功能矩陣。Visitor的接口名字和其接受的派生類類型分別是功能矩陣的兩個(gè)變化軸。
優(yōu)點(diǎn): 使用Visitor模式,使程序中的數(shù)據(jù)結(jié)構(gòu)(原類)獨(dú)立于它的用途。
用途: 一般如果應(yīng)用程序中存在有需要以多種不同方式進(jìn)行解釋的數(shù)據(jù)結(jié)構(gòu),就可以使用Visitor模式。比如使用Visitor模式來遍歷所有的配置數(shù)據(jù)來初始化不同的應(yīng)用程序子系統(tǒng)。最常見的應(yīng)用:遍歷大量的數(shù)據(jù)結(jié)構(gòu)并產(chǎn)生不同類型的報(bào)表。
缺點(diǎn):會(huì)破環(huán)組合類的封裝。
Null Object
意圖: 提供一個(gè)沒有任何行為的對(duì)象。
動(dòng)機(jī): 消除代碼中四處存在的無效對(duì)象判斷
適用性: 只要對(duì)無效對(duì)象的判斷邏輯多次出現(xiàn)時(shí),就有引入Null Object的必要。
結(jié)構(gòu): Null Object肯定是作為派生類的一個(gè)種類出現(xiàn),并用于取代沒有合適派生類可用的情形。比如,對(duì)象放在Map中,查找可能無效。
優(yōu)點(diǎn): 消除對(duì)無效對(duì)象的判斷邏輯,提供系統(tǒng)的可靠性。
---------------------------------------------------
兄弟的公司:立即購(gòu)--手機(jī)購(gòu)物,誠(chéng)信網(wǎng)購(gòu)
兄弟的公司:立即團(tuán)
歡迎轉(zhuǎn)載,請(qǐng)注明作者和出處
總結(jié)
以上是生活随笔為你收集整理的设计模式学习(五):行为型模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VC++程序调试
- 下一篇: Standard C Library -