設計模式簡介
相信你只要接觸過軟件編程,那么一定聽說過設計模式。所謂設計模式,是為解決特定問題,一套通用的、可重用的軟件設計方案。我們通常所說的設計模式,是針對面向對象語言而言。對于每一位使用面向對象語言的從業者,在學習完該語言的基礎知識后,也一定了解如何編寫面向對象的程序。但是,面向對象究竟有什么好處,我們又應該如何靈活運用面向對象來設計程序呢?
1. 面向對象
面向對象出現之前,程序是面向過程的。兩者在軟件設計上有著很大的不同。
面向過程,我們首要思考邏輯過程是什么,如何設計這個過程。
面向對象,首先要考慮的是有哪些對象,對象有什么行為,最后才是行為的邏輯。
面向對象的可以讓你程序的設計和真實世界更為契合。這會帶來如下優點:
- 現實世界有千百年積累下來數以萬億計的優秀設計,無論是具體的機械設備,還是方法論,或者工程理論。我們都可以拿來作為軟件設計的參考。
- 面向對象開發出的軟件,讓其他開發者更容易理解。我們每個人都熟知我們所生活的世界。面向對象可以讓枯燥的代碼更加鮮活,甚至憑你的經驗,也能猜出對象的某個行為應該是怎樣的邏輯。
夸了半天面向對象,你可能會想,面向對象確實不錯,我所使用的語言也是面向對象的,那我編寫的程序天然也就擁有了面向對象的優點。這種想法是錯誤的。語言僅僅是個工具,而面向對象編程是一種思維。如果對面向對象編程沒有深入理解,那么你寫出的程序,也只是披著面向對象的外衣而已。此外,即使你充分理解了面向對象的思維,也不一定能夠靈活運用面向對象解決問題。那么,此時就輪到設計模式出場了!
2. 設計模式來自哪里
設計模式不是憑空想出來的。作為通用的設計方式,設計模式是跨語言的。要想做到跨語言,那么它的根基一定是萬物都要遵守的規律。設計模式來源于真實世界,前輩們通過不斷地歸納總結、實踐,將一些已經存在的設計理論運用于軟件領域,并很好地解決了軟件設計上的問題。最終呈現給我們這些豐富的設計模式。
當我們學習設計模式之后,就可以深刻體會到為什么設計模式來源于真實世界。這里我先舉個例子,比如訂閱者模式。一聽名字你一定可以映射到現實生活中某些類似的方式,比如訂報紙,訂牛奶。訂的人就是訂閱者,送的人就是發布者。發布訂閱的核心思想,再加上軟件的特性,就構成了訂閱者模式。
3. 設計原則
那么使用設計模式能為軟件開發帶來什么好處呢?這要從設計模式的設計原則說起,一般來說有6大原則,如下:
- 單一職責原則
顧名思義,一個類最好只有一個職責。這樣的好處是引起類發生變化的原因會很少。我們開發新需求的時候,就會很少去修改這個類。而且職責越單一也越容易被復用。 - 開閉原則
軟件應該對擴展開放,對修改關閉。通俗易懂的說,就是你的軟件不能因為加功能,就不斷地修改已有的類。而是應該通過增加類,以插拔的方式來實現。舉個例子,Macbook的變壓器插頭是可以替換的,如果說某一天插口的標準換了,那么蘋果只需要開發一個新的插頭就好了,而不需要重新開發整個變壓器。開閉原則確保了代碼最大程度的可復用性。并且確保了成熟代碼的穩定性。
- 里氏代換原則
子類型可以替換掉自己的父類。這意味著我們編寫的軟件,所有使用父類的地方,都可以替換為子類對象,而程序的行為不會發生改變。通過里氏代換原則,我們可以實現開閉原則,通過增加子類實現新的功能,而不是不斷地修改父類。在需要的地方則用子類代替父類。如何實現里氏代換原則呢?首先子類不能重寫父類的非抽象方法,一旦重寫了非抽象方法,就會改變父類的行為。但是子類可以增加自己的方法和屬性,以此達到擴展的目的。 - 依賴倒轉原則
簡單說就是應該依賴接口,而不是實現。也就是我們常說的面向接口編程。這樣類和類之間就不會直接依賴,從而能夠實現開閉原則。類依賴接口,當需要擴展的時候我們可以替換實現。 - 迪米特法則
也稱為最少知道原則。如果兩個類沒有必要直接通信,那么兩個類就沒有必要相互作用??梢酝ㄟ^第三方來間接調用。類之間的耦合度越弱,越容易被復用。在弱耦合的關系中,一個類的修改,造成的影響會很小。所以我們在做設計的時候需要考慮哪些應該對外暴露,哪些應該封裝起來。不同功能模塊間的調用,應該由更為高層的類來實現,從而屏蔽掉底層的實現。 - 接口隔離原則
接口隔離原則指導你如何設計接口。不要讓接口變得臃腫,而是應該把接口按照行為不同細拆。比如你要生產一把可以拼刺刀的步槍,那它應該實現兩個接口,刀的接口和槍的接口。而不是使用一個接口覆蓋所有刀和槍的所有行為。這樣不同的接口可以組合使用。而且如果你只需要刀或者槍的行為,可以單獨實現需要的接口, 不需要實現一個大而全的接口,從而去實現很多用不到的方法。
如果你的代碼滿足以上設計原則,就會更為健壯、靈活和優雅。那么如何做到上面這些原則呢?很簡單,學習好設計模式,靈活運用設計模式解決你的問題。
4. 為什么要學習設計模式
前面已經給出了設計模式的定義----為解決特定的問題,一套通用的、可重用的軟件設計方案。我們面對的問題不一樣,需要選擇不同的設計模式來解決問題。
這就好比木匠有 20 種工具,分別用于做不同的事情。而設計模式就是軟件設計的工具,根據你遇到的問題不同,供你選擇使用。而學習設計模式的目的,就是讓你熟知工具的樣子,工具能夠做什么事情,解決什么樣的問題。當你再遇到設計問題時,自然就會想到采用什么設計模式來解決。
設計模式有多厲害呢?我可以講一個親身經歷,曾經我有一位同事寫了一段代碼來完成一個功能。code review時,我和他說你可以看一下設計模式,這段代碼使用XX模式來實現會更為的優雅。兩天后他找到我說:“設計模式太厲害了!感覺我前幾年代碼都白寫了!” 你不要覺得夸張,他的這個感覺,也是我初學設計模式后的感覺----原來程序還可以這么寫!以前我們解決問題的工具是錘子、斧子,而現在全都是機械化工具。設計模式就是這么神奇的東西。
5. 學習基礎
只要你掌握了一門面向對象的編程語言,并且熟悉面向對象的相關知識即可。當然如果有一定的編程基礎更好。此外需要了解一些UML相關的知識,方便理解類圖。
6. 小結
本節從面向對象講起,講解了什么是設計模式,程序設計的原則有哪些,為什么要學習設計模式。設計模式是寫好程序的根基。我們常常提到代碼要高內聚、松耦合,代碼要健壯等等。這些優秀代碼的特性,全都來自于設計模式。足以見得設計模式的重要性。本小結內容比較多,總結如下: