1. 程式人生 > 其它 >淺談設計模式的六大原則

淺談設計模式的六大原則

轉 https://www.cnblogs.com/liuzhenbao/p/12831090.html

一、前言

不知道大家是否有這樣的體會,就是在學習設計模式的時候,看了很多書籍,也照著很多示例把每個模式挨個敲了幾遍,但過了一段時間後,就會忘了一大半。或者有的朋友嘗試在業務編碼中使用,卻越用越複雜,本來一個類幾個方法能搞定的業務,套用模式後會多出好多介面和類,所以用著用著就放棄了。我說的比較直接點,很多教材或部落格中使用Animal、Fruit、Car這些例子來教設計模式,初衷是好的,但真沒多大用,甚至會誤人子弟。

最近筆者再次學習了設計模式(不知道是這些年的第多少次了),突然有了些感悟。我儘量用最簡單通俗的語言描述出我想表達的,有的觀點可能比較偏激或不太適合所有人,但如果大家能從這篇文章中GET到一兩個點,那也值了,哈哈。

下面我先以我個人的想法簡單粗暴地理解一下設計模式的六大原則。Show Time!

二、六大原則

2.1、單一職責原則

  • 官方解釋:單一職責原則(SRP:Single responsibility principle)又稱單一功能原則,面向物件五個基本原則(SOLID)之一。它規定一個類應該只有一個發生變化的原因。

  • 大白話:一個類只有一個發生變化的原因,我只能說在業務編碼中不太可能,或很維做到。其實大家不必糾結於有幾個讓類發生變化的原因。個人建議你想實踐單一職責原則,最好先養成良好的編碼規範,如果你平時寫程式碼,一個類裡不管什麼業務方法都往裡塞,一個方法裡巢狀著各種判斷,再好的原則也幫不也你。

  • 實踐:和類名不相關的業務不要放在這個類裡,和方法名不相關的程式碼請拆成單獨的子方法。還有當你在定義一個介面、類或方法的時候,從業務的角度用心地多想一下:這段程式碼放這裡真的合適嗎?

2.2、里氏替換原則

  • 官方解釋:里氏替換原則(Liskov Substitution Principle LSP)面向物件設計的基本原則之一。里氏替換原則中說,任何基類可以出現的地方,子類一定可以出現。LSP是繼承複用的基石,只有當衍生類可以替換掉基類,軟體單位的功能不受到影響時,基類才能真正被複用,而衍生類也能夠在基類的基礎上增加新的行為。

  • 大白話:這個原則其實還是很好理解的,主要是約束子類的行為,要求其行為和基類保持一致,如果替換為子類後,程式執行不正常,則說明子類沒有按基類的預期實現業務,或者說子類不適合繼承這個基類,對不起,請找適合的基類繼承。

  • 實踐:如果子類從一個基類繼承後,實現基類定義的虛方法時感覺很彆扭痛苦的時候,請考慮一下是否一定要從這個基類繼承。

2.3、依賴倒置原則

  • 官方解釋:依賴倒置原則(Dependence Inversion Principle)是程式要依賴於抽象介面,不要依賴於具體實現。簡單的說就是要求對抽象進行程式設計,不要對實現進行程式設計,這樣就降低了客戶與實現模組間的耦合。

  • 大白話:多用介面和抽象類,少用實現類(工具類除外)。大家看框架原始碼的時候應該能感覺到,大神在實現框架的時候到處都是介面或抽象類,而自己的程式碼卻是一大片的實現類,其實直接用實現類是沒有問題的。架構方法中有一句叫可擴充套件性,其實介面和抽象類就是實現可擴充套件性的基石。當需要擴充套件原有邏輯的時候,別人用介面和抽象類的直接加個新子類繼承下,你用實現類的到處一大片一大片的改,請回答我,有沒有?

  • 實踐:寫程式碼的時候多考慮擴充套件性,如果這段程式碼以後擴充套件或變化的可能性很高,請用介面或抽象類封裝下,抽象出不變的介面,將變化的部分留給不同的實現類。

2.4、介面隔離原則

  • 官方解釋:介面隔離原則(Interface Segregation Principle,)使用多個專門的介面比使用單一的總介面要好。一個類對另外一個類的依賴性應當是建立在最小的介面上的。

  • 大白話:這個原則和單一職責原則有點象,好吧,其實很難區分的。主要區分點在“職責”和“隔離”兩個詞上。職責要求按類的功能單一性定義介面、類、方法。隔離要求最細化的定義介面,儘量避免大而全的介面,不然介面一改,所以的實現類一片報紅,請回答我,有沒有?

  • 實踐:情願讓類實現多個單一介面,也不要實現一個大而全的介面。

2.5、迪米特原則

  • 官方解釋:迪米特法則(Law of Demeter)又叫作最少知識原則(Least Knowledge Principle 簡寫LKP),一個類對於其他類知道的越少越好,就是說一個物件應當對其他物件有儘可能少的瞭解,只和朋友通訊,不和陌生人說話。

  • 大白話:電視劇經常有這個臺詞:“你知道的太多了”,然後一槍被崩了。這個原則也是這個道理,就是一個類儘量減少和其他類組合,這樣能減少類之間的耦合,如果實現要關聯,可以通過第三者(朋友)。門面模式和中介者模式就是這個原則的體現。

  • 實踐:一個類裡,儘量減少與太多的類接觸,如果不可避免,可以用一箇中介類代替。

2.6、開閉原則

  • 官方解釋:在面向物件程式設計領域中,開閉原則規定“軟體中的物件(類,模組,函式等等)應該對於擴充套件是開放的,但是對於修改是封閉的”,這意味著一個實體是允許在不改變它的原始碼的前提下變更它的行為。該特性在產品化的環境中是特別有價值的,在這種環境中,改變原始碼需要程式碼審查,單元測試以及諸如此類的用以確保產品使用質量的過程。遵循這種原則的程式碼在擴充套件時並不發生改變,因此無需上述的過程。

  • 大白話:其實這個原則實操性不強。如果這個原則是思想的話,上面的五個原則就是這個思想的實踐,如果我們程式碼真的能做到職責單一、面向抽象程式設計且清爽的編碼規範,則會很容易實現開閉原則。但現實情況是,我們的程式碼模組與模組,類與類高度耦合、很難見到介面或抽象類、甚至全是面向過程編碼。所以在實際業務中,我們改一點程式碼,都要涉及很多專案、類、方法。改完很自信地說:我改動不大,不會影響線上業務的,不用測試,直接上線。請回答我,有沒有?

  • 實踐:儘量避免修改原有的程式碼(一點不改也不太可能),前期編碼的時候留好擴充套件點,使用繼承增加新子類的方式修改原有業務。

三、總結

  • 在學習設計原則和模式的時候,請先保證自己寫出的程式碼是整潔且符合規範的,不然再好的原則和模式也拯救不了你那一大坨一大坨的類和方法,最起碼的讀你寫的某一個方法的時候,不用拖滾動條。

  • 真正的理解你所在公司的業務和需求,先在產品和文件級別上簡化業務、理清編碼的思路,這樣更準確地找出業務的變化點和擴充套件點。

  • 設計模式其實就是封裝變化,所以編碼的時候多用心變化點,有變化了就考慮抽象出介面或抽象類。當然,在實際業務中,多是增刪改查,如果一昧的到處定義介面,也會增加複雜度,這些可以自己權衡或按團隊的編碼規範實施。

  • 不要刻意地去背這些模式或者照著敲幾遍,沒用的!實際業務編碼中,發現業務變化或擴充套件點後再去找適合的模式。

備註:以上觀點,純屬個人理解,如果有理解錯誤,勿噴!

更多精彩文章,大家可關注我的公眾號

轉https://www.cnblogs.com/liuzhenbao/p/12831090.html