C 必知必會(3)設計模式

2021-04-12 17:49:19 字數 2776 閱讀 4370

c++設計模式

對 於任何還不熟悉設計模式的人來說,在對這個領域進行簡短的縱覽之後,可能會留下這樣的印象:設計模式是乙個市場營銷大**,它不過是一些簡單的程式設計技術, 或者不過是計算機科學家(這些科學家沒事應該多出來走走)的玩物。儘管這些印象都有那麼一點道理,然而設計模式的確是職業

c++程式設計師工具箱中不可或缺的元件。

設 計模式是乙個被反覆談論的架構主題,它為特定上下文中的常見設計問題提供了解決方案,並描述了這種解決方案的結果。設計模式不僅僅是對技術的簡單描述,它 還是從現有的成功實踐一點一滴匯集起來的設計智慧型的具名封裝,並以容易交流和復用的方式編寫而成。模式關乎程式設計師之間的順暢交流。

從 實踐的角度來看,設計模式具有兩個重要的屬性。首先,它們描述了經過驗證的、成功的設計技術,這些技術可以按上下文相關的方式進行定製,以便滿足新的設計 場合的要求。其次,並且可能更重要的是,在提及某個特定模式的應用時不僅包括其中用到的技術,還包括應用該模式的動因以及應用後所達到的效果。

這 類事情並不是什麼新東西。考慮乙個來自演算法領域的模擬(需要說明的是,演算法不是設計模式,也不是「程式設計模式」,它們只是演算法,這裡只不過是乙個模擬而 已)。考慮(我可能對乙個同事作的)如下宣告:「有乙個未排序的序列,必須要進行很多次搜尋。因此,希望對其進行快速排序,並且使用二分查詢來執行每乙個 查詢。」能夠使用術語「快速排序」和「二分查詢」,這種價值是不可估量的,不但在設計方面如此,在就該設計與受過教育的同事進行交流時也是如此。當我說 「快速排序」時,我的同事知道我正在排序的序列具有隨機訪問結構,並且它的排序時間複雜度為

o(nlog2

n),同時該序列中的元素可以採用類似小於操作符進行比較。當我說「二分查詢」時,我的同事知道(即使事先沒有提到「快速排序」)序列已經被排序過了,定位感興趣的元素所執行的比較操作的時間複雜度為

o(log2

n), 並且存在乙個適當的操作來對序列中的元素進行比較。標準演算法所具有的共享的知識以及標準詞彙表,不但允許高效地記錄文件,而且允許對設計方案進行有效的評 議。比方說,如果我計畫對乙個單向鏈結表結構來執行這個查詢和排序過程,我的同事立刻會自鳴得意地哈哈大笑,並指出在這種情形下我不能使用快速排序並且可 能不希望使用二分查詢。

在 設計模式出現之前,在對物件導向設計的文件化、交流以及高效地評議方面,這些優點都不具備。我們被迫低水平地描述我們的設計,這種方式低效且不夠精確。這 並不是說用於複雜物件導向設計的技術尚不存在,而是這些技術尚未以乙個共享的、通用術語的方式為整個程式設計社群所用。設計模式解決了這個問題,我們現在可以 像描述演算法設計一樣高效、毫無歧義地描述物件導向設計。

舉個例子,當我們看到

bridge

模 式被應用到某項設計中時,我們知道在乙個簡單的機制層面,抽象資料型別實現被分離成乙個介面類和乙個實現類。此外,我們知道這樣做的原因是為了將介面從實 現強有力地分離出來,這樣,對實現的改變將不會影響到使用介面的使用者。我們還知道這種分離會帶來執行期開銷,知道應該怎樣對抽象資料型別的源**進行布 局,還知道許多其他細節。模式的名字是關於某項技術的諸多資訊和經驗的高效且無歧義的「控制代碼」,在設計和文件中小心並正確地使用模式和模式術語,可以使代 碼和設計更加明晰。

那些嚴謹的模式專家有時以某種文獻的形式來描述模式(他們確實是這麼做的),這種描述遵循某種正式的結構。還有幾種常見的變體也在使用,但不管哪種描述方式,均包含以下

4個必不可少的部分。

首先,設計模式必須具有乙個毫無歧義的名字。例如,術語「包裝器(

)」對於設計模式命名來說就沒有什麼意義,因為它早已被廣泛使用並且具有許多不同的含義。使用「

」這樣的術語來命名某種設計模式只會帶來混淆和誤解。實際的做法是,以前在「

」名下的設計技術現在分別被指派為「

bridge

」、「strategy

」、「facade

」、「object adapter

」以及其他一些模式名字。使用精確的模式名字比使用不那麼精確的名字具有「明顯」的優勢,就像術語「二分查詢」比「查詢」更精確、更有意義一樣。

其次,模式描述必須定義該模式所能解決的問題。這種描述可以相對寬泛,也可以相對狹窄。

再次,模式描述要記述該問題的解決方案。根據陳述的問題,該解決方案可以相對高階,也可以相對低階,但無論如何,它應該具有足夠的通用性,以便可以根據問題可能出現的不同上下文進行定製。

最後,模式描述要記述將該模式應用於某個上下文的後果。在應用該模式後,該上下文是如何發生改變的?不管是變好,還是變壞。

擁 有模式的知識可以使一名糟糕的設計師搖身一變成為一名優秀的設計師呢?呃,是給出另乙個模擬的時候了:設想你被迫學習某一門讓人痛苦的數學課,它的期末考 試內容是證明某個數學領域中的許多定理。如何才能從這門課中死裡逃生呢?當然,最顯而易見的方式是成為乙個天才。你從最初的原理開始,進而研究整個數學分 支的基礎知識,最終證明那些定理。乙個更為實際的途徑是,你牢記並消化該數學領域中的大量定理,並使用你所具備的任何天賦的數學能力、靈感以及好運去選擇 適當的輔助定理,然後以某種邏輯「膠水」將它們粘合在一起,從而最終證明新的定理。是的,甚至對於那些「傳說中的天才」來說,這種方式都是很有優勢的,因 為基於現成的定理來證明會更高效,同「凡夫俗子」交流起來也更容易。當然,熟悉輔助定理並不能保證乙個可憐的學數學的學生通過考試,但這類知識至少可以使 其能夠理解別人給出的證明。

同樣的道理,從最初的原理進而到複雜的物件導向設計也是頗為無趣的,而且與他人交流最終設計也很困難。組合使用各種設計模式來生成物件導向設計,類似於在數學中使用輔助定理來證明乙個新的定理。設計模式常常被描述為「微架構(

micro-architecture

)」,它們可以與其他模式進行組合從而生成乙個新的架構。當然,選擇適當的模式並有效地對其進行組合,也是需要設計方面的專家經驗和天資稟賦的。不過,一旦設計完成後,甚至你的經理都能夠理解完整的設計方案,只要他具備一些必需的模式方面的知識即可。

C 必知必會(3)

class x public xoperator const x const 二元取餘操作 xmemfunc1 const x voidmemfunc2 可以採用中綴或函式呼叫語法來呼叫這個過載的操作符 如下 x a,b,c a b c 採用中綴語法呼叫成員操作符 a b.operator c 成員...

C 必知必會

條款2 多型 2 條款3 設計模式 5 條款4 stl 8 條款5 引用是別名而非指標 10 條款6 陣列形參 13 條款7 常量指標與指向常量的指標 16 條款8 指向指標的指標 19 條款9 新式轉型操作符 21 條款10 常量成員函式的含義 25 條款11 編譯器會在類中放東西 29 條款12...

mysql 必知必會 3

排序檢索資料 1.排序資料 order 排序 乙個列或多個列,進行排序輸出 select 列名 from 表名 order by 列名 多列排序 先列名1排序,再列名2排序 select 列名1,列名2 from 表名 order by 列名1,列名2 指定排序的方向。資料排序預設是公升序排序,降序...