摘要:不少人對設計模式都有些疑問或者說是質疑:寫代碼一定要用設計模式嗎?用了設計模式的代碼就比沒用的好嗎?
本文分享自華為雲社區《走近設計模式:寫代碼一定要用設計模式嗎?》,原文作者:技術火炬手 。
不少人對設計模式都有些疑問或者說是質疑:
- 寫代碼一定要用設計模式嗎?
- 用了設計模式的代碼就比沒用的好嗎?
為了解答第一個問題,我們需要去調研一下什么是設計模式,這包括了解設計模式產生的初衷、設計模式能否幫我們解決軟件問題等;而為了解答第二個問題,就需要去掌握如何使用設計模式,何時何地使用何種設計模式,什么時候應該使用、什么時候需要遠離。
什么是設計模式?
前段時間面試候選人的時候問過這個問題——“什么是設計模式?”。候選人答到,“設計模式有單例模式、觀察者模式、代理模式......“。我沒有打斷他,還是順着問了他對這幾個模式的理解。雖然這並不是我想問的,但我猜測會這樣回答的人應該不在少數。
“設計模式”或者是“Design Patterns”,無非是一種設計的模式,設計這里是指軟件設計,再具體一點是“面向對象的軟件設計”,而模式這個概念比較籠統,各行各業都有模式,用白話說就是一種“套路”,是一種可以復制的經驗。
提起設計模式,有一本繞不開的經典《設計模式:可復用面向對象軟件的基礎》,除了設計模式,還有一個副標題——可復用面向對象軟件的基礎,限定了復用和面向對象。書中首先是拋出了幾個觀點:
- 設計面向對象軟件比較困難,而設計可復用的面向對象軟件就更加困難。
- 有經驗的面向對象設計者能做出良好的設計,而新手卻無從下手。
- 不是解決任何問題都要從頭開始,內行的設計者更願意復用以前使用過的解決方案。
然后給出了一個不是很好理解的設計模式的定義:對用來在特定場景下解決一般設計問題的類和相互通信對象的描述。講人話就是特定問題的可復用的解決方案。這里可復用的概念比較含糊,我更願意理解為實際項目中總結出來的,解決特定問題的最佳實踐。
這種最佳實踐可以來自於他人總結,典型的來源是各種書籍和源碼;還有一個更重要的來源便是自身軟件開發經驗的總結。
什么時候使用什么模式?
解決特定問題的最佳實踐。顯然解決問題A的最佳實踐往往並不能解決問題B,至少不會是解決問題B的最佳實踐,那么我想這里至少要面臨兩個問題:
- 某種設計模式解決的是什么問題?
- 我的問題等於某種設計模式解決的問題嗎?
得到了上面兩個問題的答案后,接下來的才是設計模式如何解決我的問題。
這兩個問題是以我的思路提出來的,同時我也覺得這是兩個很糟糕的問題,下面我會做說明。
首先,我並不建議新手直接學習如何使用各種設計模式,比如那23種。學習的結果往往是掌握了如何用編程語言實現某種設計模式,卻對該設計模式解決了什么問題沒有深刻的印象。這種先入為主會讓學者覺得設計模式很簡單,然后在實際的開發中為了使用模式而使用,並沒有解決實際的問題。因為我是這么干的,所以覺得有更好的方式。
一個建議是,在新手階段,按這個步驟去學習設計模式:
- 多花點時間去了解軟件設計上有哪些常見的設計問題、疑難雜症
- 哪些問題已經有了最佳實踐的解決方案,或者說設計模式,哪些還沒有
- 深入體會設計模式解決該問題的過程,最好能親身參與該過程
這個思路是先有問題后有模式,大腦中形成的思路是通過問題檢索模式,而不是孤立的模式,或者是模式檢索問題的回路。
到這里我們在看一下上面兩個問題,是一種拿着答案找問題的思路。實際的場景應該拿着問題找答案。我們重新調整一下:
- 我要解決的問題是什么?
- 我的問題是否等於已經存在的問題A
- 是否有解決問題A的設計模式
通過學習有哪些常見的設計問題以及對應的模式,我們也只能回答問題3。
而問題1和問題2跟設計模式沒有任何關系,卻是能不能應用某種設計模式的第一步。這也是導致設計模式濫用的根源,同時也是很多人放棄設計模式的原因。
關於如何去回答這兩個問題,小弟暫時沒法給大家解答。分析問題的能力,可能需要時間的積累吧。
設計模式的牢籠
設計模式按解決特定問題的最佳實踐來定義本身沒有錯,但往往有人陷進了設計模式的牢籠。
以GoF設計模式為例,雖然那23中設計模式是由比你我更加聰明的程序員總結出來的,但使用它們也不是沒有代價的。
- 設計模式不是現成的代碼,它不像類庫可以直接使用
- 設計模式大都是解決代碼擴展性的問題,但這里的擴展性真的是你需要的嗎,是不是過度設計
- 設計模式提升擴展性的方式往往是增加抽象,這就犧牲了簡單性
這里再看一下開篇的兩個問題:
問:寫代碼一定要用設計模式嗎?
答:不是,不是所有問題都有現成的解決方案。
問:用了設計模式的代碼就比沒用的好嗎?
答:不是,也許更差。
學習設計模式的好處
雖然設計模式不是銀彈,掌握設計模式也不一定能幫你解決你正面臨的問題,但學習一下設計模式對你的軟件開發工作還是大有裨益的,就算你永遠不使用它。
如果不忽悠下讀者學這個還是有點用的,那寫后續的系列文章意義在哪......
1.應對面試中的設計模式相關問題
就很直接,如果你是被面試的,被問到的概率不低;如果你面試別人,可以用來考察下候選人的理解程度。
2.讓讀源碼、學框架事半功倍
優秀的開源項目中類的個數都會比較多,類結構、類之間的關系極其復雜,常常調用來調用去。為了保證代碼的擴展性,代碼中會使用到很多設計模式,當然也不排除作者秀的嫌疑,但是如果你不懂設計模式,看開源代碼經常摸不着作者的設計思路,看起來找不到北。
3.為你的職場發展做鋪墊
公司里面code review,你連幾個設計模式都說不出來,一看就不是“大牛”,嗯,就是這樣的。
4.提升你的代碼設計能力
這一點要看造化,但這是客觀存在的,你總會遇到需要設計復雜系統的時候,早接觸早准備。