現在還需要學習設計模式嗎?

語言: CN / TW / HK

最近面試了不少人,Java 和 dotNET 的都有,當問到設計模式時,大部分都只能説出單例和工廠,有些能聊聊其他的一些模式的,大多也沒有在實際項目中用過。為了團隊成員能有更好的編碼能力,便有了重新寫寫設計模式的想法,寫作也是一個重新學習的過程。

平時我們寫代碼,會有這樣一些情況:

1、Leader 分配一個任務,比如要添加一個新功能,便找到相關的類,添加新的方法,然後就開始寫業務邏輯,各種循環、判斷,直到業務功能完成;

2、修復一個 Bug ,需要修改歷史代碼,某個方法被其他很多地方調用,怕改動引發出新的問題,有時複製一個相同方法進行修改;有時在方法參數中添加可空參數,然後根據參數值做判斷。

上面的做法都是最直觀、簡單的方法,不需要動腦筋,一個程序員按照這種方法,工作一年便能輕鬆應對日常工作,工作十年,可以稱之為擁有一年經驗的熟練工,永遠成不了高手。

如果一個團隊都像這樣做事,時間長了,會出現各種問題:

1、代碼看着有很多類似的,但每個地方又有些差別,不敢隨意修改;

2、Bug 修復異常困難,容易漏掉場景;

3、擴展功能會牽一髮而動全身,需要加班加點,弄的疲憊不堪;

設計模式便是要打破我們的思維慣性,避免我們偷懶,強制我們思考的一個工具。

當再遇到上面提到的任務或  Bug 修復時,可以換一種方式來思考:

1、分析新增功能的邊界和範圍,和現有功能的關係;

2、結合現有功能和新增的部分,看是否需要提取接口、類是否需要拆分、方法是否需要合併、參數是否需要擴展;

3、整理出第一版設計後,就開始進行編碼,過程中發現問題及時調整重構;

4、在不斷優化過程中,會慢慢發現,最後的代碼就符合某種模式了,所以説設計模式不是去生搬硬套,而是按照面向對象的設計原則逐步優化出來的。

現在所説的設計模式是基於面嚮對象語言,在面嚮對象語言中有很多的設計原則,在學習設計模式前需要了解並掌握這些設計原則,原則的靈活運用最終就體現成了各種模式,常用的原則有:

1、單一職責原則(SRP):一個類應該僅有一個引起它變化的原因;

2、開放封閉原則(OCP):類模塊應該是可以擴展的,但是不可以修改(多擴展開放,對修改封閉);

3、Liskov 替換原則(LSP):子類必須能夠替換他們的基類;

4、依賴倒置原則(DIP):高層模塊不應該依賴於底層模塊,二者都應該依賴於抽象;抽象不應該依賴於實現細節,實現細節應該依賴於抽象;

5、接口隔離原則(ISP):不應該強迫客户程序依賴於他們不用的方法;

6、迪米特法則(LOD):最小知識原則,類之間不該有直接關係的不要依賴,必須要有依賴關係的只依賴必要的抽象類或接口。

而到具體模式的學習就不得不提 GoF 23 種設計模式,這些設計模式在歷史性的一本經典著作《設計模式:可複用面向對象軟件的基礎》中被描述的,這本書的四位作者並稱為 Gang of Four(GoF) 。

現在市面上各種設計模式的書籍以及其他資料都是源於這 23 種,發展到今天模式已經遠遠不止 23 種,但我們只要學會了其根本就能夠應對各種變化。

我們寫代碼時,引入任何的中間價、類庫、權衡之下,肯定是利大於弊,我們才會使用,設計模式也是一樣,如果只是盲目跟風,套用模式,會變成過度設計,得不償失。初學者往往會犯這樣的錯誤,覺得學習的模式得在項目中使用才行,找準時機就去套用。在學習過程中這樣進行練習是可以的,但真實項目中,一定得去思考現在的方式有什麼樣的問題,為什麼需要進行重構,然後才是思路和方法,得到最終的模式。

設計模式常常會按照創建型、結構型和行為型進行分類,其實很多模式並不常用、很多模式有很多的相似性。根據我自己的經驗,我認為一個好的學習路徑是:

1、先學習面向對象,然後掌握面向對象的設計原則;

2、學習常用的模式,多個模式可以對比起來學習;

3、搞懂模式能解決什麼問題,和相似的模式應該怎麼區分和選擇;

4、結合實際的開發場景學習怎麼應用;

5、閲讀下 dotNET Core 源碼,看看能不能發現使用了哪些設計模式。

後續的文章也大致會按照這個思路進行,不會按照常規的順序、也不一定會每一個都介紹到,儘量做到最有價值的輸出。

最後想説的是,程序員都應該學習設計模式,尤其是能養成一個使用設計思維的方式去處理問題更是一個程序員的必修課。