新手閱讀Gof的《設計模式》有點難度,這里,要講述的是,幫助大家奠定一下基礎,使大家更好的去學習設計模式,去提升我們的思想,設計包含着抽象,又有些哲學,靜下心來,你也可以學到優秀程序員的技術。
設計模式,起初是從建築學中開始發展的。在此來講個故事。
很久很久以前~~~(^_^),有一個建築師,他修建了許多建築,當地的人都十分尊敬他,因為他修建的房屋,是最牢固最美觀的,但是他自己一直在問自己:“質量可以客觀評價嗎?”這位建築師最感興趣的一種美就是建築質量:是什么讓我感覺一個建築設計是優秀的?
“評價一個建築物是否美觀”不僅僅是一個品味的問題。還需要通過可以衡量的客觀標准來描述美觀程度,比如質量,創意什么的。
我們軟件的構建,也如同建築學一樣。需要設計,需要規划,它們有太多的相似的地方了。
我們也可以試着問自己:
優秀設計能表現而劣質設計不能表現什么?
劣質設計能表現而優秀設計不能表現的又是什么?
嗨!是否很矛盾呢?
沒關系,故事還沒講完,建築師觀察了許多的建築,城鎮,街道,以及人們的生活環境。他發現,對於任何特定的建築物,優秀的結構之間,總有一些相同之處。
建築結構不相同,他們類型相同,盡管如此,他們仍是高質量的。
比如說我們每天使用的電腦,新產品的型號不同,但是他們終究是電腦,他們既然要銷售,電腦就必須是高質量的。(你見過劣質電腦,能打鋪天蓋地的廣告嗎?)
建築師通過這樣的方式,觀察解決相似問題的不同解決方案,一步步縮小他的關注焦點,他可以洞察出優質設計之間的相似之處,並把這些相似之處稱為”模式”。
聰明的建築師,把模式定義為“在某一個情景下的問題解決方案”。
每個模式,通過一種讓你可以無數次使用這一解決方案、而不必再次重復同樣的工作方式,描述一個在我們環境中重復出現的問題,並描述該問題解決方案的核心。
用簡單的例子來描述一下這個有點復雜的概念:
建築師需要修建一個庭院。
然后建築師就會對於這個庭院有自己的構思:庭院可以享受陽光,享受星辰,要有私有的戶外空間,需要些花花草草,有條件修建個小水池也不錯。
然后建築師,再向庭院主人詳細問下個人的獨特需求,然后建築師就能開工。
在這里,建築師的思考過程,就是我們所提到的模式,模式它有一個名稱,在這里就是個庭院模式。然后他有個目的:幫助人們在其中生活。
為什么說這個庭院是一個優秀的庭院?建築師修建了許許多多的庭院,他知道什么樣的庭院才是適合人們的,符合人們習慣的,他有經驗。然后它可以復用自己的經驗,優秀的建築師所設計的,一定是美的。
經驗,可以使人們少走彎路,借鑒經驗,從而加速達成目的。
模式幾乎存在所有的設計問題中。
每個模式描述,都由下面4個組成部分:
- 模式的名稱
- 模式的目的,它要解決的問題
- 我們如何實現它
- 為了實現它我們必須考慮的限制和約束
建築師有一顆追求美的心。
好啦^_^,故事講完啦,我們回到正題,軟件設計模式。
“四人組”的《設計模式》是一部經典之作,很經典。
也許你都看過這本書了,知道這里面收錄了23個模式。
在這需要認識到的是:
這幾位作者並不是書中這些模式的創建者。幾位作者識別除了那些已經存在於軟件社群中的模式,“從特定問題的優質設計中學到的經驗”。
任何一個模式描述都需要包括下面的基本要素:
名稱 | 每個模式都有一個獨一無二名稱,人們用名稱來鑒別模式 |
意圖 |
模式的目的 |
問題 | 模式視圖解決的問題 |
解決方案 | 對於自己出現的場景中的問題,模式怎樣提供一個解決方案 |
參與者和協作者 |
模式包括的實體 |
效果 | 使用模式的效果,使用模式的同時研究其約束 |
實現 | 怎樣實現模式。實現只是模式的具體表現形式。 |
Gof參考 | 在四人組的書中得到更多信息的位置 |
現在大家應該知道什么是設計模式了吧?現在再來完成一個大家疑惑的問題。
為什么要學習它們?
我們知道,學習寫模塊化的軟件,能使軟件復用。
現在要讓大家知道,學習設計模式,能夠復用解決方案,通過復用已經建立的設計,能為自己遇到的問題找到更高的起點,並避免了繞彎路。
受益於學習別人的經驗。不必再為普通、重復的問題重新設計解決方案。有沒用聽起來很熱血澎湃的感覺?最起碼我是如此,代碼重用不厲害,思想重用才厲害^_^。
第二點:
建立通用的術語,在交流於協作時,都需要一個共同的詞匯基礎、一個對問題的共同觀點。設計模式在項目的分析和設計階段提供了一個通用的參考點。
第三點:
對於問題、設計過程和面向對象,模式給你一個更高的層次的視角。你能從過早處理細節的通病中解放出來。(別以為處理細節不嚴重,繁瑣的細節,讓我崩潰,深有感觸T-T)
不好理解這一點? 沒關系,看個簡單的模擬場景:
假設有兩個木匠正在討論如何為櫥櫃制作抽屜的問題。
木匠1:”你認為我們應該怎樣制作這些抽屜呢?“
木匠2:“我想我們應該這樣做結合部分,在木材上直鋸下去,然后回轉45°鋸,然后再直鋸下去,再朝另一個方向回轉45°鋸,再....然后......”(他在扯細節問題!!)
現在,你的的工作就是弄明白他們究竟在說些什么!看看分解之后的:
這里有些誇大了,真正的木匠師傅,並不會真的在細節的層次上說話,他們會用專業術語。
木匠1:我們應該用一個燕尾接合還是一個斜面接合?
這就是上面說的,建立通用術語,然后在高層次講述問題。假如讓你選擇和他們其中一個人合作,你會選擇誰?
模式能讓我們同時看到樹木和森林。
第四點:
學習設計模式,最重要的原因:它,能改表你的思想,讓你成為更有力的分析者。
第五點:
它能提高你的效率,頭腦思考的效率。別人是單核,而你是雙核,這多么爽呀?
五點足夠讓你很有成就感了,其實好處不僅僅只有這些。
當在團隊中,設計模式既可以幫助單個開發者學習,也可以幫助團隊開發。這是因為,團隊中的低級成員看到懂得設計模式的高級開發者從模式中獲益,於是這些低級成員也想得到這些好處,這為他們學習這概念提供了有理的動機。
大多數設計模式還讓軟件更具可修改性,需求永遠都在變,能適應變換的設計模式,讓維護軟件成為一種輕松的工作,還有什么理由不去學習?
我們知道,底層建築決定高層建築,在某種程度上,高層建築能也能反饋底層建築更多的信息。
在設計模式被正確傳授時,可以大大增加學習者對基本面向對象設計原則的理解。(對於這一點,我是深有感觸)在我學習設計模式時,使用它們來說明基本面向對象概念(封裝、繼承、多態等)在你學習了一些設計模式之后,即使你並不直接使用設計模式,你也會在自己的設計問題中使用這些策略。
設計模式還有一個優點,能讓你或你的Team可以為不需要巨大繼承體系的復雜問題創建設計方案。
總結:
學習這些可以幫助你:
- 復用現有的、高質量的、針對常見的重復出現問題的解決方案。
- 建立通用的術語,改善團隊內部的溝通。
- 將思考轉移到更高的視角。
- 判斷是否擁有正確的設計,而不僅僅是一個可以運行的設計。
- 改善個人學習和團隊學習。
- 改善代碼的可修改性。
- 促進對改良設計的選用,升值在沒有明確使用模式的時候。
- 發現“龐大的繼承體系”的替代方案。
(吐血,下面又是第二寫!!!自動保存個又坑我。以后再也不拿這個網頁寫隨筆!)
好處差不多講完了,現在來看些能夠提高理解設計模式的具體方法。
has-a關系和is-a關系:
為什么要講這個關系?園子里其實有人已經講過這兩個關系。我覺得這兩個關系本該通俗易懂的,用簡單的例子里整合一下,免得新手再去找相關關系去理解,太麻煩。(知道此關系的可以跳過此處,看看下面的UML介紹^_^)
has-a關系:
一個類“包含”另一個類。
一個簡單的比喻就是,汽車他就是一個has-a的關系,汽車由各種配件組成,方向盤,發動機,輪胎等。
使用組合的可以把簡單的東西組合成一個系統。組合就意味着可替換,一部分壞了,你可以選擇修,也可以選擇換。換好之后意味着,整個系統依舊良好的運行。
組合還有個優點,使用組合可以獨立創建系統和子系統,更重要的是可以獨立的進行測試和維護。(我深知其中好處,各種復用啊)
組合有兩種類型,一種是關聯(也叫組合,為了區別一下,我用關聯),一種聚合。
關聯:汽車就是關聯,它由各個組件組合而成。
聚合:輪胎就是個很好的例子。
is-a關系:
“是一個”關系。看看圖:
UML圖可能大家還沒熟悉,下面我也會簡單介紹一下,幫助大家打下閱讀UML圖的基礎。
在這里我可以說:狗是一種動物,代碼表示就如下
Dog D=new Dog(); Mammal M = D;
這沒錯,狗和頭有關系,但我們不能這么寫:
Dog D = new Dog(); Head H = D;
這明顯是錯的,狗有頭,但有頭的不一定是狗,它可以是別的。比如貓。
在這個圖的關系中,我們還可以給狗命名,就好像這樣寫:
Dog D = new Dog(); Nameable N = D;
它運行的很好,也很自然,一個名字代表一條狗。
在這個關系圖中,我們用到了繼承和接口。
我們知道,能繼承的不僅是基類,它也可以是接口。
繼承和接口都是構成is-a關系的簡單而有效的證據。啰嗦一點,接口其實也有個關系在里面:
can-do關系:看一個接口的時候,主要看它能做什么。例如:一個類型能將自己的實例轉換為另一個類型(IConvertible),用過Framework 提供的接口的同學,更能體會。
組合和繼承是創建類的主要形式。
包含往往比繼承更可取,除非你要對“is-a“關系建模。
繼承是一種有用的工具,但它卻會增加復雜度,復雜度是軟件管理的首要殺手。
UML基本語法注解:
方法內"+"表示Public,“-”表示Private,還有一個“#”這里沒有提到,表示Protected,它很少用到。
在方法后面,還有一些setName:void和getName:String只代表這個方法的返回類型。
括號內的就是參數列表。
這張圖我們要關注的就是那個空心箭頭,它表示繼承。金毛獵犬繼承於狗類。
這個就關注空心棱形。它表示組合,方向盤是汽車的一部分。
這個也簡單。連接線就是代表關聯,客戶端和服務端就是關聯的,再看一張前面介紹過的圖:
虛線三角箭頭代表繼承自接口,而接口的描述方式就是箭頭指向的樣子interface。
使用UML來輔助設計非常有用,這里簡單的介紹是為了讓大家更能看懂設計模式的類圖說明,UML的完整講述就需要一本書了。
盡管UML重要,但學習OO技能更為重要,先學習OO的基礎概念,才能看懂UML圖。
圖是輔助,輔助大腦更好的思考。
但這里提議的是:
無論你用什么例子,都應該把注意力放在OO概念上。
好了,基礎就講述這么多了,願大家在設計模式的學的輕松^_^