連載:麵向對象葵花寶典:思想、技巧與實踐(38) - 設計模式之道
很多人能夠熟練背誦出所有的設計模式,能夠快速畫出各種設計模式的UML類圖,也能夠熟練的寫出《設計模式》一書中各個模式的樣例代碼。但一到實際的項目設計和開發的時候,往往都會陷入迷茫:要麼無從下手,不知道哪個地方要用設計模式;要麼生搬硬套,胡亂使用設計模式,將方案和代碼搞得一團亂麻。
【知易行難 —— 設計模式應用的問題】
形而下者謂之器,形而上者謂之道。
---《易經·係辭》
正如很多流行的技術(麵向對象、UML等)一樣,幾乎大部分人都會宣稱自己“掌握、熟練掌握”,甚至“精通”,然而,真正掌握的或者精通的,實在是少之又少。
一種典型的現象是:很多人能夠熟練背誦出所有的設計模式,能夠快速畫出各種設計模式的UML類圖,也能夠熟練的寫出《設計模式》一書中各個模式的樣例代碼。但一到實際的項目設計和開發的時候,往往都會陷入迷茫:要麼無從下手,不知道哪個地方要用設計模式;要麼生搬硬套,胡亂使用設計模式,將方案和代碼搞得一團亂麻。
這是什麼原因呢,難道是設計模式不好用,或者設計模式根本就是一個噱頭?
答案不在於設計模式本身是否有用,而是在於我們沒有掌握正確的學習和應用設計模式的方法。
學習《設計模式》一書中的23個設計模式,隻是掌握了《設計模式》的“器”,但並沒有掌握設計模式的“道”。就像一個工匠,鋸、鑽、錘、刨樣樣精通,但如果不知道什麼地方該用鋸,什麼地方該用鑽,肯定是一個不合格的工匠。為了能夠更好的學習和應用設計模式,我們也需要掌握設計模式的“道”。
設計模式的“道”就是用來指導我們什麼時候用設計模式,為什麼要用設計模式,23個設計模式隻是告訴了我們how,而設計模式之道卻可以告訴我們why和where!
【撥雲見日 —— 尋找設計模式之道】
熟悉《設計模式》一書內容的同學可能會想到:《設計模式》一書中,不是每個模式都有“適用性”的說明麼?這個其實就是回答了where和why的問題啊!
例如:Facade模式的“適用性”說明如下(摘自《設計模式》中文版一書):
上麵這一段文字,看起來回答了where和why的問題,但實際上我個人感覺作用並不大。
首先,這段描述太長了:以上這段文字是否花了你幾分鍾的時間去閱讀和理解?
其次,這段描述比較抽象:什麼事複雜,什麼叫做簡單,什麼叫做很大依賴性。。。。。。可能每個人理解都不一樣。
再者,23個模式,所有的“適應性”條款加起來估計有幾十條條,你能夠背住麼?即使你能夠全部背住,你能夠全部理解麼?即使你能夠全部理解,當麵對一個具體問題的時候,你知道幾十條裏麵哪一條適應你的情況麼?
所以,《設計模式》一書關於“適用性”的描述,實際上還是太複雜,太多了,不具備很強的實踐知道意義和可操作性。
我們需要的是一個更簡單的指導思想,大道至簡,最好是一兩句話就能夠描述!
幸運的是,答案竟然就在《設計模式》一書中,但這個答案並不是那麼明顯!
《設計模式》一書的內容側重點是23個模式的詳細闡述,大部分人可能都是直奔主題,逐一去研究每個模式,而對於開頭部分第1章和第2章的內容並沒有詳細研讀和思考,或者對於這兩章隻是簡單的瀏覽,並未認真領會和思考,由此錯過了最重要的內容。再加上GoF在這2章的內容中,既要引入一個全新的概念,又要提綱挈領的介紹各個模式,還要引入實例進行分析,以至於大量的內容將真正核心的內容反而給淹沒或者衝淡了。
設計模式之道就隱藏在“2.6.2 封裝實現依賴關係”的最後一段,很簡單的一句話:
對變化的概念進行封裝(encapsulate the concept that varies)
你看到這句話可能有點失望,前麵分析了那麼久,賣了那麼多的關子,結果就這麼簡簡單單一句話,這不是在忽悠麼?
你可千萬別小看了這句話,“大道至簡”,設計模式之道也不例外,但“簡”並不意味著沒用,相反,正因為其“簡”,每個人的理解才一致,也更好掌握,實踐中才更好應用。正所謂:“真傳一句話,假傳萬卷書”。
GoF在《設計模式》一書中最早提出這個原則,後來不斷的有其他專家進行闡述,其中《設計模式精解》(《Design pattern explained》)一書的闡述我認為是最精辟的:Find what varies and encapsulate it,翻譯一下即“找到變化,封裝變化”。雖然含義和GoF描述的基本一致,但其更加容易理解。
正所謂:踏破鐵鞋無覓處,得來全不費工夫!
【庖丁解牛 —— 解析設計模式之道】
現在,讓我們來深入理解“找到變化,然後封裝變化”的設計模式之道。
首先,“找到變化”解決了“在哪裏”使用設計模式的問題,即回答了“where”的問題。
“找到變化”看起來是比較抽象的一句話,但在實踐中非常好應用和操作,而且不同領域、不同行業的係統都可以完美的應用這句話。雖然不同領域、不同行業變化的因素、方式、時機等都不一樣,但每個領域或者行業的需求分析人員、設計人員,對自己所處行業和領域的可能變化肯定是有比較深刻的理解的,什麼會變化、會如何變化、什麼時候會變化。。。。。。等等,肯定都能夠自己判斷,這種判斷並不需要什麼高深的技巧和知識水平,隻需要一定的經驗積累。
如果我們剛接觸一個行業或者領域,經驗積累並不夠,那怎麼辦呢?是否就無法“找到變化”了?
其實也不然,有一個萬能的辦法,隻是要花費更多的精力了。
我的這個萬能辦法就是“唯一不變的是變化本身”,也就是說,如果你不知道什麼會變化,那麼就抱著懷疑一切的想法,一切都可能是變化的。
但光有這條指導原則還不行,如果我們真的抱著“一切都是可能變化的”想法,然後封裝一切變化,那麼就會陷入變化的漩渦無法自拔,因為變化是會遞歸的,A可能變成B,B也可能繼續變化,於是這樣無窮無盡,係統是不可能做出來的。
所以我們需要一個終止條件,避免陷入無窮無盡的變化遞歸漩渦。這個終止條件就是“有限時間內可能發生的變化”。這裏的“有限時間”隨行業和領域的不同而變化。例如(以下時間僅供參考):
互聯網行業可以說:半年內可能發生的變化。。。。。。
電信行業可以說:1年內可能發生的變化。。。。。。
金融行業可以說:2年內可能發生的變化。。。。。。
政府行業可以說:3年內可能發生的變化。。。。。。
有了這個指導原則後,你可以這樣去問有經驗的前輩、大蝦、大牛等: XXX在1年內會發生變化麼?會怎樣變化?
就這樣,即使你是菜鳥,通過這麼一招“借花獻佛”,也能夠輕鬆發現“變化”的地方。
其次,“封裝變化”解決了“為什麼”使用設計模式的問題,即回答了“why”的問題。
為什麼我們要用設計模式,是因為我們要封裝變化!但我們為什麼要封裝變化呢?
答案很明顯:變化不好!
當然這個“不好”不是從業務的角度來說的,而是從係統的角度來說的。從業務的角度來說,“變化”是好的,變化意味著新的機會;但從係統的角度來說,變化並不好,因為變化必然要求係統改動,改動就意味著風險!
雖然變化給係統帶來風險,但我們不能因此而“拒絕變化”,因為拒絕變化就意味著失去了機會,簡單來說,賺不到錢的係統,設計再優美,功能再強大,係統再穩定,也不過是一堆無用的擺設:
客戶給你提了新需求,你不做,能拿到合同麼。。。。。。
行業正在興起新的流行功能,你不做,你的係統有人用麼。。。。。。
一項創新帶來了新的機遇,你不做,能搶占市場麼。。。。。。
所以我們要“擁抱變化”,但我們又不能讓變化帶來太大的風險,所以就提出了“封裝變化”。“封裝變化”意味著將變化的影響範圍控製最小,將風險降到最低。
我們來看看,變化會帶來哪些問題和風險:
1)開發人員需要編碼以適應變化,設計不好的方案將導致大量的編碼工作量、自測工作量;
2)測試人員不單要測試因變化而新增的那部分,還要測試受影響的部分,設計不好的方案,牽一發而動全身,導致測試工作量大大增加;
3)如果為了適應某個變化而對係統做了比較大的改動,則係統的質量風險將上升,很可能導致上線失敗,或者上線後出現各種問題;
因此,我們要盡量減少變化帶來的工作量和風險,而減少的最有效方法就是將變化的影響範圍縮小,即:將變化封裝起來,使其隻在有限的範圍內有影響。
【舉一反三 —— 活學活用設計模式之道】
就像一個武林高手有了深厚的內功,天下萬物皆可成為手中的利器,而不必拘泥於具體的武器和招數一樣,掌握了設計模式之道後,我們其實也完全可以不拘泥於隻是用《設計模式》一書中的23個設計模式,可以根據需要選擇最合適的方案。
例如:
不同的業務有不同的規則排列組合,規則引擎可以封裝各種變化的規則。。。。。。
類之間的依賴是變化的,Spring使用XML配置文件來封裝這種變化。。。。。。
每個銀行的卡都不一樣,銀聯封裝了這種變化,使得不同銀行可以互通。。。。。。
總之,你可以使用類和設計模式來封裝變化,你也可以使用配置文件和模塊來封裝變化,你也可以使用一個係統來封裝變化。。。。。。
================================================
轉載請注明出處:https://blog.csdn.net/yunhua_lee/article/details/38315995
================================================
最後更新:2017-04-03 05:39:38