程式碼設計 六大原則
單一職責原則 Single Responsibility Principle
定義:一個類或者一個介面,最好只負責一項職責。
問題由來:類T負責兩個不同的職責P1和P2。由於職責P1需要發生改變而需要修改T類,就有可能導致原來執行正常的職責P2功能發生故障。
解決方法:遵循單一職責原則。分別建立新的類來對應相應的職責;這樣就能避免修改類時影響到其他的職責;
當遇到職責擴散的時候,在邏輯足夠簡單的時候,才可以在程式碼級別上面違反單一職責原則,只有類中方法數量足夠少,才可以在方法級別上違反單一職責原則;
優點:類的複雜性將會降低,可讀性將會大大提高,維護性也會提高。
里氏替換原則 Liskov Substitution Principle
在使用基類的地方可以任意使用其子類,能保證子類完美替換基類;這一種精神其實是對繼承機制約束規範的體現。在父類和子類的具體實現中,嚴格控制繼承層次中的關係特徵,以保證用子類替換基類時,程式行為不發生問題,且能正常進行下去。
對於繼承來說,父類定義了一系列的規範和契約,雖然不強制所有的子類必須遵從,但是如果子類對這些非抽象方法任意修改,就會對整個繼承體系造成破環。
如果非要重寫父類的方法,比較通用的方法是:原來的父類和子類都繼承一個更加通俗的基類,原有的繼承關係去掉,採用依賴、聚合、組合等關係代替;
原則包含了一下四層含義:
* 子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法;
* 子類可以增加自己特有的方法;
* 當子類的方法過載父類的方法時,方法的形參要比父類方法的輸入引數更佳寬鬆;
* 當子類的方法實現父類的抽象方法時,方法的返回值要比父類更加嚴格;
依賴倒置原則 Dependence Inversion Principle
定義:高層模組不應該依賴低層模組,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象,其核心思想是依賴於抽象;
問題由來:類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的程式碼來完成;這種場景下,類A一般是高層模組,負責複雜的業務邏輯;類B和類C是低層模組,負責基本的原則操作;假如修改類A,會給程式帶來不必要的風險。
解決方案:將類A修改為依賴介面I,類B和類C各自實現介面I,類A通過介面I來間接與類B和類C發生聯絡,則會降低修改類A的機率;
在實際中,我們一般需要做到以下三點:
* 低層模組儘量都要有抽象類或者介面,或者兩者都有;
* 變數的宣告型別儘量是抽象類或者介面;
* 使用繼承時遵循里氏替換原則;
介面隔離原則 Interface Segregation Principle
定義:客戶端不應該依賴它不需要的介面;一個類對另一個類的依賴應該建立在最小的介面上,否則將會造成介面汙染;類A通過介面I依賴類B,類C通過介面I依賴類D,如果介面I對於類A和類B來說不是最小介面,則類B和類D必須去實現它們不需要的方法;
原則的含義是:建立單一介面,不要建立龐大臃腫的介面,儘量細化介面,介面中的方法儘量少;就是說,我們要為每個類建立專用的介面,而不要試圖去建立一個龐大的介面供所有依賴它的類去呼叫;
注意,介面儘量小,但是要有限度,對介面進行細化可以提高程式設計靈活性,但是如果過小,則會導致介面數量儘量小,使設計複雜化。所以一定要適度,為依賴介面的類定製服務,只暴露給呼叫的類它需要的方法,它不需要的方法則隱藏起來;
規則:
* 一個介面只服務於一個子模組或業務邏輯,服務定製;
* 通過業務邏輯壓縮介面中的public方法,讓介面看起來更加精悍;
* 已經被汙染了的介面,儘量修改,如果變更風險太大,則用介面卡模式進行轉化;
* 根據具體的業務,深入瞭解邏輯,用心感知去控制設計思路;
如何實施介面隔離,主要有兩種方法:
1. 委託分離,通過增加一個新的介面型別來委託客戶的請求,隔離客戶和介面的直接依賴,注意這同時也會增加系統的開銷;
2. 多重繼承分離,通過介面的多重繼承來實現客戶的需求;
迪米特法則
定義:一個物件應該對其他物件保持最少的瞭解,其核心精神就是:不和陌生人說話,通俗之意就是一個物件對自己需要耦合關聯呼叫的類應該知道的少;這會導致類之間的耦合度降低,每個類都儘量減少對其他類的依賴。
合成複用原則
原則是儘量使用合成/聚合的方式,而不是使用繼承;
開閉原則
定義:一個軟體實體如類、模版和函式應該對擴充套件,對修改關閉;
解決方案:當軟體需要變化時,儘量通過擴充套件軟體實體的行為來實現變化,而不是修改已有的程式碼來實現變化;
- 單一職責原則:實現類要職責單一;
- 里氏替換原則:不要破壞繼承體系;
- 依賴倒置原則:面向介面程式設計;
- 介面隔離原則:設計介面的時候要精簡單一;
- 迪米特法則:降低耦合;
開閉原則:總綱,對擴充套件開放,對修改關閉;