天天看點

從設計模式的設計原則感悟生活

從設計模式的設計原則感悟生活

設計模式中的很多思想還是很有意思的,剛畢業的時候接觸設計模式感覺有點高深,坐而論道,感覺還是有些虛,平時做的小練習還能自己搗鼓一番,自己使用一下設計模式,然後大刀闊斧的改動代碼,随心所欲,寫完以後還能熱乎勁上來高興幾天,時間長了就忘了很多的東西,隻是感覺設計模式就是抽象,自己感覺也抽象。如果死磕着問自己,估計大腦裡還是沒什麼印象了。到了工作中,又發現有些功能或者思想固然好,但是要在已有的項目中做一些改動,一下子又有點不知所措,時間長了,思想和行動就脫節了。工作中以面向對象為目标,實際中做着結構化的思路開發。

設計模式的這幾個原則自己是看了忘,忘了以後時間長了也忘了看了。如此惡性循環。

看别人總結的原則描述很是詳盡,但是看代碼還是不夠通俗,自己也來搗鼓一下,從自己的思路和了解來總結總結設計模式和工作生活的聯系。

1

單一職責原則(Single Responsibility Principle)

定義:不要存在多于一個導緻類變更的原因。即一個類隻負責一項職責。

  • 一種加班的原因

    在生活中我可以了解這裡所說的職責就是每個人的工作職責或者技能,在公司,你就是員工,在具體的工作中,可能負責開發,測試,設計,需求等等。

    比如說開發,大體上可能有前端開發,背景開發,如果劃分語言種類,可能有java開發,c++,php開發

    java開發可能還有可能是嵌入式,web等

    在工作中為什麼分這麼多的種類,而且很細,出發點也就是為了提供工作效率,優化工作,比如我們做項目,在項目A裡面可能是設計java的swing開發,這個職責就和明确了,不會牽扯涉及到c++之類的内容,我們就可以設想,有一個很粗粒度的類做了工作的種類劃分,一直細化到java 的swing開發,那麼在這個項目的過程中,從原則上講我隻負責java swing開發的内容,在整個項目周期中我扮演了java開發工程師的swing開發部分職責。如果稍候有人找我做c#的webservice的聯調測試,說這也是java swing工作師的職責,那麼不好意思,這個不屬于我的工作範圍。可能這個時候就有上司來重新設定一個崗位是c#的webserive的開發工作,另外找一個人來做這個工作,如果人手不夠,那麼我就是身兼兩職。顯示工作中這種情況可能比較多:).可能一個人幹着好幾種工作,對于工作來說,實作這種完全的清晰劃分還是有些困難,但是從個人成長來說是不錯的。

  • 更新檔的噩夢

在系統中發生各種各樣的問題是很常見的,可能對于一些比較緊急的問題,就需要提供更新檔了,但是更新檔可以解決問題,如果是高手就從根本上分析問題,找到問題的根源,從源頭上解決,當然這種改動可能涉及的改動範圍比較大,對于緊急更新檔而言是不現實的,那麼就頭痛醫頭,腳疼醫腳,先做一些不是很規範嚴謹的改動。等更新檔上去了,之後各種各樣的原因,變更就這麼遺留下來了。等到之後的人來看的時候,又會抱怨代碼寫的太差,太不規範了,但是讓他改,他還是沒底,于是乎這種“懶惰”的保守思想保留了下來,直到第20個人進入了項目,發現一個方法幾百幾千個if-else,代碼都不知道改從何該起。。。

這個也就說明了對于系統中出現的複雜校驗,可以盡可能的提前做優化改進,保證功能的完整和單一,随着系統規模變大,模糊,不穩定的校驗就會導緻系統更嚴重的問題。

2

裡氏替換原則(Liskov Substitution Principle)

定義1:如果對每一個類型為 T1的對象 o1,都有類型為 T2 的對象o2,使得以 T1定義的所有程式 P 在所有的對象 o1 都代換成 o2 時,程式 P的行為沒有發生變化,那麼類型 T2 是類型 T1 的子類型。

定義2:所有引用基類的地方必須能透明地使用其子類的對象。

解決方案:當使用繼承時,遵循裡氏替換原則。類B繼承類A時,除添加新的方法完成新增功能P2外,盡量不要重寫父類A的方法,也盡量不要重載父類A的方法。

  • 可口可樂的全球統一口味
可口可樂在全球都奉行着統一的标準,使得在任何地方口味都基本一緻。我們可以了解可口可樂的産品秘方是一個類,全球的可口可樂都給予它來作為生産的标準,用軟體設計的角度來說,全球各地的可口可樂公司都是基于父類的産品标準,沒有對可口可樂的口味有任何改動,如果基于不同的口味,可以根據情況定制,但經典的口味還是保留不變。
  • 山寨的興起和次品,劣品
說了可口可樂,來舉個反例,比如說市面上蘋果手機很暢銷,國内的一些公司就開始複制了蘋果的外觀和基本的界面效果,有了所謂的High phone,但是蘋果的核心的使用者體驗和産品性能這些特性廠商也沒辦法繼承複制下來,因為蘋果公司不可能給它這些東西。那他就自己來做,最後隻要看起來界面主題和外觀和蘋果手機差不多就行了。從軟體設計的角度來說,山寨産品繼承了蘋果手機的一些特性,但是有些核心特性沒有的時候,子類就重寫了父類的方法,這樣使用效果和感官也大打折扣。

同樣次品,劣品的道理也是類似,我就不多說了,你懂的。

3

依賴倒置原則(Dependence Inversion Principle)

定義:高層子產品不應該依賴低層子產品,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。

解決方案:将類A修改為依賴接口I,類B和類C各自實作接口I,類A通過接口I間接與類B或者類C發生聯系,則會大大降低修改類A的幾率。

  • 買火車票
大家這些年買火車票比以前友善多了,以前基本都是通過車站的視窗或者黃牛來買,後來有了一些代理,買票就不用跑那麼遠了,前幾年,鐵道部開放了網上購買車票的方式,買票更友善了,現在還可以電話訂票,通過其他的網站代理來買票。可以說買票的途徑有很多種。可以了解買票時一個抽象的行為,我們隻依賴于抽象,保證能買到票就行,至于通過哪種管道,根據大家自己的情況。這樣我們買票就依賴于抽象不依賴于具體的實體了。
  • 發送郵件的郵件組
在工作中,郵件組還是很有工作效率的,比如公司有一個技術支援部門,設定為一個郵件組,在部門内部做了郵件的各種轉發政策,保證華北區的客戶問題發送到指定的人的郵箱中,如果支援的人有多個,那就都發送給他們,現在客戶有一個問題,他就直接發送給這個技術支援的郵件組。他無須知道具體要發送給哪一個人,隻要這個問題能夠得到回報和解釋就可以了。這就是依賴倒置所要表達的中心思想。

4

接口隔離原則(Interface Segregation Principle)

定義:用戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。

問題由來:類A通過接口I依賴類B,類C通過接口I依賴類D,如果接口I對于類A和類B來說不是最小接口,則類B和類D必須去實作他們不需要的方法。

解決方案:将臃腫的接口I拆分為獨立的幾個接口,類A和類C分别與他們需要的接口建立依賴關系。也就是采用接口隔離原則。

  • 醫院買藥的怪事

    在醫院買藥的時候,有時候會碰到這種情況,比如我需要吃一闆藥,可能大夫開藥的時候會給你開一個大盒,或者一大包,理由就是藥都是包好的,一次一包一大盒,不拆開賣的。我們可以了解一闆藥提供了一個短期的治療效果,是一個簡單接口,但是醫院裡面如果把一大盒藥拆開,就沒法分開賣了,這樣就把這個問題的影響轉移給了患者,讓患者為這種情況買單。因為醫院買藥的接口是一個大接口,使用者需要去實作那樣他們不是很需要做的事情

  • 臃腫的機構和辦事效率

    臃腫的機構和辦事效率以前大家去各種機關辦事,各種複雜的流程,各種蓋章,各種簽字,少一個都不行,隻認章不認人。可能一個機關有很多的辦事部門,因為以前的流程過于落後,可以了解為一個很大的接口,結果去辦事的時候還要去做一些額外的蓋章簽字,準備各種材料,比如部門a已經提供了完整的個人資訊材料,部門b還要從頭再來,一個步驟都不能少,這樣這個接口太大,辦事的時間也拖的挺長。如果有一些小的接口,比如快捷的網上便民服務等等就是小的接口,這樣效率也高很多。

5

迪米特法則(Law Of Demeter)

定義:一個對象應該對其他對象保持最少的了解。

解決方案:盡量降低類與類之間的耦合。

  • 工作彙報
工作中我們經常要彙報工作的情況,但是從上司的角度而言,他更關心結果,不是過程,是以你在彙報工作的時候涉及太多的細節,會把自己引入一個無形的漩渦中,比如報告中提到了一個細節,和a部門同僚a有什麼關系,然後領到問你同僚a的情況,問這個問題,然後又牽扯出部門b的另一個同僚,這樣解釋了半天,發現還把上司弄糊塗了。迪米特法則就是最少知道原則,隻要言簡意赅的說明,那些實作細節等等就不需要過多的牽扯了。
  • 微信中的留言功能
在微信的朋友圈中,如果你有好友a,b,c,但是好友a,b卻互相不認識,那麼你發的一些狀态圖檔等,他們都能看到,他們給你回複的時候,朋友a看不到朋友b的留言,從根本上保證了使用者的隐私,這也是微信中和微網誌中的一個不同點。微信的朋友圈更側重個人的一些資訊,不會暴露過多的資訊。

6

開閉原則(Open Close Principle)

定義:一個軟體實體如類、子產品和函數應該對擴充開放,對修改關閉。

解決方案:當軟體需要變化時,盡量通過擴充軟體實體的行為來實作變化,而不是通過修改已有的代碼來實作變化。

  • oracle 中的Long類型
如果大家用Oracle資料庫,就會發現oracle已經在很早的版本中使用了long的資料類型,但是使用中碰到了一些問題,發現沒有預想的那麼好,于是産生了lob的資料類型,但是oracle的産品已經提供了很多完善的功能,為了後續的支援,不能把這部分變更徹底去掉,徹底去掉就不相容低版本了。是以在後續的版本中明确提出舍棄了long類型,更是在一些操作中限制了它的使用,但是還是沒有從根本上把它去除,開閉原則在這裡就是oracle為了支援低版本的功能,對于擴充開放,引入了新的資料類型,但是對修改關閉,不能徹底的改動long類型。
  • 領土問題
從這個角度最後來提一句,對于領土問題也是如此,對于擴充開放,如果能夠擺正态度,有一個能夠正常談判的氛圍,那麼對于擴充是開放的,但是單方面的修改肯定是關閉