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

dbhelper發表於2014-11-26

設計模式中的很多思想還是很有意思的,剛畢業的時候接觸設計模式感覺有點高深,坐而論道,感覺還是有些虛,平時做的小練習還能自己搗鼓一番,自己使用一下設計模式,然後大刀闊斧的改動程式碼,隨心所欲,寫完以後還能熱乎勁上來高興幾天,時間長了就忘了很多的東西,只是感覺設計模式就是抽象,自己感覺也抽象。如果死磕著問自己,估計大腦裡還是沒什麼印象了。到了工作中,又發現有些功能或者思想固然好,但是要在已有的專案中做一些改動,一下子又有點不知所措,時間長了,思想和行動就脫節了。工作中以物件導向為目標,實際中做著結構化的思路開發。
設計模式的這幾個原則自己是看了忘,忘了以後時間長了也忘了看了。如此惡性迴圈。
看別人總結的原則描述很是詳盡,但是看程式碼還是不夠通俗,自己也來搗鼓一下,從自己的思路和理解來總結總結設計模式和工作生活的聯絡。

單一職責原則(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,程式碼都不知道改從何該起。。。

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

里氏替換原則(Liskov Substitution Principle)

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

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

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

  • 可口可樂的全球統一口味

可口可樂在全球都奉行著統一的標準,使得在任何地方口味都基本一致。我們可以理解可口可樂的產品秘方是一個類,全球的可口可樂都給予它來作為生產的標準,用軟體設計的角度來說,全球各地的可口可樂公司都是基於父類的產品標準,沒有對可口可樂的口味有任何改動,如果基於不同的口味,可以根據情況定製,但經典的口味還是保留不變。

  • 山寨的興起和次品,劣品

說了可口可樂,來舉個反例,比如說市面上蘋果手機很暢銷,國內的一些公司就開始複製了蘋果的外觀和基本的介面效果,有了所謂的High phone,但是蘋果的核心的使用者體驗和產品效能這些特性廠商也沒辦法繼承複製下來,因為蘋果公司不可能給它這些東西。那他就自己來做,最後只要看起來介面主題和外觀和蘋果手機差不多就行了。從軟體設計的角度來說,山寨產品繼承了蘋果手機的一些特性,但是有些核心特性沒有的時候,子類就重寫了父類的方法,這樣使用效果和感官也大打折扣。

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

 

依賴倒置原則(Dependence Inversion Principle)

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

解決方案:將類A修改為依賴介面I,類B和類C各自實現介面I,類A透過介面I間接與類B或者類C發生聯絡,則會大大降低修改類A的機率。

  • 買火車票

大家這些年買火車票比以前方便多了,以前基本都是透過車站的視窗或者黃牛來買,後來有了一些代理,買票就不用跑那麼遠了,前幾年,鐵道部開放了網上購買車票的方式,買票更方便了,現在還可以電話訂票,透過其他的網站代理來買票。可以說買票的途徑有很多種。可以理解買票時一個抽象的行為,我們只依賴於抽象,保證能買到票就行,至於透過哪種渠道,根據大家自己的情況。這樣我們買票就依賴於抽象不依賴於具體的實體了。

  •  傳送郵件的郵件組

在工作中,郵件組還是很有工作效率的,比如公司有一個技術支援部門,設定為一個郵件組,在部門內部做了郵件的各種轉發策略,保證華北區的客戶問題傳送到指定的人的郵箱中,如果支援的人有多個,那就都傳送給他們,現在客戶有一個問題,他就直接傳送給這個技術支援的郵件組。他無須知道具體要傳送給哪一個人,只要這個問題能夠得到反饋和解釋就可以了。這就是依賴倒置所要表達的中心思想。

介面隔離原則(Interface Segregation Principle)

定義:客戶端不應該依賴它不需要的介面;一個類對另一個類的依賴應該建立在最小的介面上。
問題由來:類A透過介面I依賴類B,類C透過介面I依賴類D,如果介面I對於類A和類B來說不是最小介面,則類B和類D必須去實現他們不需要的方法。

解決方案:將臃腫的介面I拆分為獨立的幾個介面,類A和類C分別與他們需要的介面建立依賴關係。也就是採用介面隔離原則。

  • 醫院買藥的怪事
    在醫院買藥的時候,有時候會碰到這種情況,比如我需要吃一板藥,可能大夫開藥的時候會給你開一個大盒,或者一大包,理由就是藥都是包好的,一次一包一大盒,不拆開賣的。我們可以理解一板藥提供了一個短期的治療效果,是一個簡單介面,但是醫院裡面如果把一大盒藥拆開,就沒法分開賣了,這樣就把這個問題的影響轉移給了患者,讓患者為這種情況買單。因為醫院買藥的介面是一個大介面,使用者需要去實現那樣他們不是很需要做的事情
  • 臃腫的機構和辦事效率
    臃腫的機構和辦事效率以前大家去各種機關辦事,各種複雜的流程,各種蓋章,各種簽字,少一個都不行,只認章不認人。可能一個單位有很多的辦事部門,因為以前的流程過於落後,可以理解為一個很大的介面,結果去辦事的時候還要去做一些額外的蓋章簽字,準備各種材料,比如部門a已經提供了完整的個人資訊材料,部門b還要從頭再來,一個步驟都不能少,這樣這個介面太大,辦事的時間也拖的挺長。如果有一些小的介面,比如快捷的網上便民服務等等就是小的介面,這樣效率也高很多。
迪米特法則(Law Of Demeter)

定義:一個物件應該對其他物件保持最少的瞭解。

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

  • 工作彙報

工作中我們經常要彙報工作的情況,但是從領導的角度而言,他更關心結果,不是過程,所以你在彙報工作的時候涉及太多的細節,會把自己引入一個無形的漩渦中,比如報告中提到了一個細節,和a部門同事a有什麼關係,然後領到問你同事a的情況,問這個問題,然後又牽扯出部門b的另一個同事,這樣解釋了半天,發現還把領導弄糊塗了。迪米特法則就是最少知道原則,只要言簡意賅的說明,那些實現細節等等就不需要過多的牽扯了。

  • 微信中的留言功能

在微信的朋友圈中,如果你有好友a,b,c,但是好友a,b卻互相不認識,那麼你發的一些狀態圖片等,他們都能看到,他們給你回覆的時候,朋友a看不到朋友b的留言,從根本上保證了使用者的隱私,這也是微信中和微博中的一個不同點。微信的朋友圈更側重個人的一些資訊,不會暴露過多的資訊。

 

開閉原則(Open Close Principle)

定義:一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。

解決方案:當軟體需要變化時,儘量透過擴充套件軟體實體的行為來實現變化,而不是透過修改已有的程式碼來實現變化。

  • oracle 中的Long型別

如果大家用Oracle資料庫,就會發現oracle已經在很早的版本中使用了long的資料型別,但是使用中碰到了一些問題,發現沒有預想的那麼好,於是產生了lob的資料型別,但是oracle的產品已經提供了很多完善的功能,為了後續的支援,不能把這部分變更徹底去掉,徹底去掉就不相容低版本了。所以在後續的版本中明確提出捨棄了long型別,更是在一些操作中限制了它的使用,但是還是沒有從根本上把它去除,開閉原則在這裡就是oracle為了支援低版本的功能,對於擴充套件開放,引入了新的資料型別,但是對修改關閉,不能徹底的改動long型別。

  • 領土問題

從這個角度最後來提一句,對於領土問題也是如此,對於擴充套件開放,如果能夠擺正態度,有一個能夠正常談判的氛圍,那麼對於擴充套件是開放的,但是單方面的修改肯定是關閉的。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-1347084/,如需轉載,請註明出處,否則將追究法律責任。

相關文章