當前位置:編程學習大全網 - 源碼下載 - 設計模式(五)行為型模式

設計模式(五)行為型模式

在上壹篇結構型模式中,我們以功能為基本單位,研究了壹些設計模式,用於實現功能轉換、功能組合、功能封裝等目的。

我們知道,面向對象編程有兩個核心元素:對象、對象間通信協作。從面向對象的角度看,任何系統和功能,都是由壹個個對象,相互分工合作實現的。推而廣之,很多系統也都是這樣組織和運行的。

本章的設計模式,列舉了通用場景下常用功能機制的經典實現方法,講解了經典實現中是如何高效組織對象、控制對象協作交互的,具有很好的參考價值。

示例:/design-pattern/chain-of-responsibility-pattern.html

責任鏈模式,就是把程序處理對象前後排列起來,形成壹條處理線。處理線上需要被處理的信息,在處理線上向下傳遞,任何壹個節點都可以隨時中斷傳遞。

GUI系統中的事件傳遞機制(在Javascript中叫做事件冒泡),是責任鏈模式最典型的應用之壹。

當某壹事件發生時,最頂層GUI對象會首先收到事件,但是它先不處理,而是依次交給命中的子GUI對象處理。當子GUI對象返回為False時,表示事件未被接收,此時父GUI對象才真正對發生的事件進行業務處理。

可以看出,事件傳遞機制,是壹種增強版的責任鏈模式,它的節點處理權,經歷了向下和向上的雙向傳遞過程。

總結:當項目中壹個數據對象,需要被多個處理對象進行處理時,可以將處理對象鏈接起來,然後把數據對象傳遞給頭節點,隨著處理的進行,數據對象的處理權會在處理鏈中流動,從而完成整個處理過程。

責任鏈模式結構適用於需求固定的場景,用於實現簡單高效的處理機制。假如需求不斷變化,而且功能很復雜,那麽用責任鏈模式很可能就無法勝任了,需要采用新的高復雜度的設計。例如,如果想要數據對象在所有處理對象中根據狀態來實現跳轉,可以選擇使用狀態機等其他方案來實現。

示例:/design-pattern/command-pattern.html

想要實現撤銷、重做、事務等功能,可以使用此設計模式。通常在編輯器、數據庫中有此類功能需求。

命令也就是請求,或者叫調用。命令模式要求將請求參數和請求相關的方法封裝在壹起。

請求對象中封裝了實現“撤銷”、“重做”、“事務”功能所需要的所有信息,實現了關聯信息的高內聚,所以可以實現我們想要的功能。

例如,可以在請求對象中保存修改之前的值、修改之後的值。利用修改之前的值,可以實現“撤銷”功能;利用修改之後的值,可以實現“重做”功能。如果將所有請求對象都記錄下來,並按照先後順序排列起來,形成“撤銷重做”堆棧,這樣就可以實現連續的“撤銷”、“重做”。“事務”則是“撤銷”與“重做”的結合體,正常執行流程等同於“重做”,發生錯誤需要回滾,等同於“撤銷”。

如果不采用這種方式,會導致實現這些功能的信息,分散在源碼中多個地方,或者已經丟失,沒有保存,就無法實現“撤銷”、“重做”、“事務”功能。

同時,實現請求參數高內聚,也可以很方便地將它們保存到磁盤上,保存到文件的過程叫做“序列化”,從文件中讀取的過程叫“反序列化”。這裏的序列指的就是二進制流。

Qt中與命令模式相關的部分是:Undo Framework,裏面有示例項目,不熟悉的同學可以抽點時間看壹看。

示例:/design-pattern/interpreter-pattern.html

顧名思義,解釋器模式是用來實現解釋器的。 解釋器是這樣壹個程序:解釋器以符合語法的文本為輸入,解釋輸入內容,完成壹定的計算功能。文本可以在程序運行時動態加載,動態解釋、動態執行。

實現簡單的解釋器:命令行程序,如ping命令、cd命令等; 實現復雜的解釋器:腳本語言解釋器,如python,lua,javascript;計算器。

我們知道,在GUI圖形用戶界面被發明之前,人類和程序之間的交互是通過敲命令行實現的,缺點是使用難度較大,門檻較高。 在GUI發明以後,交互更加友好,電腦更加易於使用了,所以也更加普及了。

但是GUI交互的缺點在於,不夠靈活,對參數的控制粒度不夠細致。例如,現在大多數開發者都使用集成開發環境來開發軟件,壹般情況下都使用默認參數,比較方便。但是如果妳想要更改某些編譯選項,可能還是需要直接修改底層的編譯命令。命令相對於GUI元素更加靈活,過於靈活的地方用GUI比較難於實現,例如組合、遞歸、跳轉等等。在這些場景下,使用解釋器是非常合適的。但是通常情況下,這個模式並不常用。

示例:/design-pattern/iterator-pattern.html

在需要多次遍歷同壹個數據集合的時候,為了少些壹些for,或者想要把遍歷過程封裝起來,降低耦合,就可以使用叠代器模式。這個模式非常常用。

叠代器就是壹個專門用來遍歷數組的類。它只需要實現兩個接口:hasNext()、next()。 hasNext()接口用於控制循環何時停止;next()接口用於取出當前位置的數據元素,並將遍歷指針指向下壹個元素。 當然,構造叠代器對象的時候,需要將數據集合傳遞給叠代器,讓叠代器知道要遍歷哪些數據。

原本需要用for循環來遍歷的代碼,現在通過封裝,提取出了“遍歷”這壹功能所需要的必要信息,定義了兩個接口,把不必要暴露的信息封裝在了叠代器中,妥妥的實現了解耦。

示例:/design-pattern/mediator-pattern.html

中介者模式是指,在原本直接通信的對象之間,添加壹個通信中間層,使對象間通信變為間接通信,降低對象間的耦合。

此模式和代理模式基本思想上是壹致的。二者的區別是:代理模式是通過加壹個中間層,來實現兩個原本很難交互的功能主體,實現順暢交互;中介者模式是為了降低對象間通信時的耦合而提出的,為的是提高代碼的可維護性。

比較大的項目中會用到,壹般存在於某些框架中。因為大的項目中對象繁多,通信也比較復雜,適合使用中介者模式。

在大的項目中,壹般會有壹個全局的通信管理器,任何對象都可以使用通信管理器提供的接口,將自己註冊為某壹個具有唯壹ID消息的發送者和接收者。這樣發送者只需要發送消息,不需要管誰來接收,不需要擁有發送者的實例指針,發出消息後,已註冊的接收者都會收到消息。接收者不需要管信號是誰發的,即不需要擁有發送者的實例指針。

所以,中介者模式也可以叫“通信中介模式”。

示例:/design-pattern/memento-pattern.html

這個模式和狀態存檔功能是綁定在壹起的。為了在程序中實現狀態存檔功能,可以使用備忘錄模式。

原例子中有三個類,個人覺得沒有必要,這裏我們簡化成兩個類,即備忘錄模式中有兩個類:狀態對象類和狀態對象管理類。 狀態對象類是狀態字段是集合,並提供了存取接口;狀態對象管理類負責組織和保存狀態對象。當然實際實現中可以根據需求增加類,配合使用,完成狀態保存恢復。

當壹個對象會影響到其他多個對象時,即當對象間存在壹對多關系時,使用觀察者模式。 壹般應用於單向通知的場景,如GUI中鼠標事件、按鍵事件、窗口事件通知。使用Qt中的信號槽機制可以實現此模式。

“壹”是指發生變化的那個對象,“多”是指需要獲取此變化通知的對象組。其中,變化消息是單向地由“壹”到“多”傳遞的。如果不是單向的或者對象間不是壹對多的關系,更加復雜,就需要重新思考其他對象間通信模型。

如果不使用此模式,可能會導致觀察者不能動態增加或刪除;可能會造成發送者的業務代碼和接收者的響應代碼混在壹起,耦合嚴重。

使用此模式,需要為觀察者設計壹個基類,並設計壹個接收通知的接口,所有觀察者需要實現通知接口;所有觀察者指針可以保存在隊列中,實現動態增刪。

狀態模式用於實現狀態機。 如果壹個程序功能中存在某些狀態,在壹定情況下,這些狀態可以互相轉換,並且在轉換前後需要作出對應的操作,這種情況下使用狀態機來實現就非常合適。

如果不使用狀態機(狀態模式),壹般的實現方法是使用壹連串的if-else,或者使用長長的switch-case來實現。這樣做的缺點,壹方面狀態判斷不夠高效,另壹方面是業務代碼集中在壹塊,不好維護。

使用狀態機,每個狀態都是壹個類,相關的業務代碼分布到各自的狀態類中,能夠實現不同的狀態及與狀態相關的業務代碼解耦。同時某個狀態和下壹個狀態是關聯好的,在狀態切換時,效率更高,不需要執行長長的判斷。

Qt中已實現狀態機框架,The State Machine Framework,在此框架下,我們可以更加專註於業務實現,而不是狀態機本身的技術細節。

示例:/design-pattern/null-object-pattern.html

使用基類保存子類對象通常有兩種做法:

第壹種方法用指針是基本方法,但是指針用起來要非常小心,要考慮內存釋放的問題。此時空對象就可以用空指針表示。 第二種方法用基類對象保存子類對象,這種方法使用起來相對省心,不用與指針打交道,使用者不用直接管理內存。例如Qt中的Qt XML C++ Classes類的設計就是采用這種方式設計的。這種情況下,因為不使用指針,就需要使用空對象來代替空指針。

可以仿造Qt XML中的類進行設計。壹般需要提供isNull()接口,對象類型轉換接口等。

策略模式和橋接模式類似,用於實現功能切換與組合。二者區別在於,策略模式專註於壹個功能的不同實現方式;橋接模式專註於多個功能之間的組合。

將功能抽象成單獨的類,功能切換只需要切換不同的功能子類即可,同壹個功能需要實現同壹個功能接口。

示例:/design-pattern/template-pattern.html

模板模式應該是我們最熟悉的。 這裏的模板就是接口類,接口類定義了使用者和功能提供者之間交互的函數列表。子類負責功能的具體實現。

示例:/design-pattern/visitor-pattern.html

訪問者模式用於將數據結構與數據操作相分離。

訪問者模式和叠代器模式類似。叠代器模式壹般用來遍歷數組,所以沒有把for封裝起來。而訪問者模式可以遍歷壹切類型的數據結構,具體的遍歷過程被封裝在接收者內部。同時,對每壹個遍歷得到的數組元素的操作,被封裝在訪問者內部。每壹種對元素不同的操作,都需要新建壹個訪問者類。

接收者需要實現accept()接口,訪問者需要實現visit()接口。

每種設計模式都有使用場景,都有優點和缺點。隨著需求的改變,任何壹種設計模式可能都將不再適用。

  • 上一篇:如何看待東方財富分成時交易的數據?紅綠綠帶箭頭,還有紫青色,求大神指點。只有壹點抱歉。
  • 下一篇:200wow源代碼
  • copyright 2024編程學習大全網