1. 程式人生 > >設計模式之七大原則

設計模式之七大原則

一、單一職責原則[Single Responsibility Principle]---一個類只負責一項職責

定義:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。 

問題由來:類C負責兩個不同的職責:職責1和職責2。當職責1的需求發生改變而需要修改類C時,可能會導致職責2的功能發生故障。

解決方案:根據單一職責原則,分別建立兩個類C1和C2,實現職責P1和職責P2的功能。再有需求改變時,修改類C1不會導致職責P2發生故障;修改類C2不會導致職責P1發生故障。

所以:不能為減少程式碼量而把牛頭和馬嘴塞在一個類中

二、里氏替換原則[Liskov Substitution Principle]---繼承與派生的規則


定義1:如果對每一個型別為 T1的物件 o1,都有型別為 T2 的物件o2,使得以 T1定義的所有程式 P 在所有的物件 o1 都代換成 o2 時,程式 P 的行為沒有發生變化,那麼型別 T2 是型別 T1 的子型別。通俗的說,即子類可以擴充套件父類的功能,但不能改變父類原有的功能
定義2:所有引用基類的地方必須能透明地使用其子類的物件。

問題由來:有一功能P1,由類C完成。現需要將功能P1進行擴充套件,擴充套件後的功能為P,其中P由原有功能P1與新功能P2組成。新功能P由類C的子類C1來完成,則子類C1在完成新功能P2的同時,有可能會導致原有功能P1發生故障。

解決方案:1)子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法;2)子類中可以增加自己特有的方法;3)當子類的方法過載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入引數更寬鬆;4)當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更加嚴格。

所以:儘量不要重寫父類已經實現了的方法,可以用介面等其他方法實現

三、依賴倒置原則[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必須去實現他們不需要的方法。

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

但是:介面隔離原則一定要適度,介面設計的過大過小都不好

五、迪米特法則[Law Of Demeter]---低耦合,高內聚

定義:一個物件應該對其他物件保持最少的瞭解。也就是說,一個類對自己依賴的類知道的越少越好

問題由來:類與類之間的關係越密切,耦合度就越大,當一個類發生改變時對另一個類的影響也越大。

解決方案:對於被依賴的類來說,無論邏輯多麼複雜,都儘量地的將邏輯封裝在類的內部,對外除了提供的public方法,不對外洩漏任何資訊。

所以:一個物件應該對其他物件保持最少的瞭解

六、開閉原則[Open Close Principle]---一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉

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

問題由來:在軟體的生命週期內,因為變化、升級和維護等原因需要對軟體原有程式碼進行修改時,可能會給舊程式碼中引入錯誤,也可能會使我們不得不對整個功能進行重構,並且需要原有程式碼經過重新測試。

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

七、組合/聚合複用原則[Composition/Aggregation Reuse Principle(CARP)]:儘量使用組合和聚合少使用繼承的關係來達到複用的原則

定義:又稱合成複用原則。在新的物件中使用已有的物件,使之成為新物件的一部分,新物件通過委派呼叫已有物件的方法達到利用其已有功能的目的。也就是說,儘量使用類的合成利用,儘量不要使用繼承

解決辦法:組合或聚合關係可以將已有的物件(也可稱為成員物件)納入到新物件中,使之成為新物件的一部分,因此新物件可以呼叫已有物件的功能,這樣做可以使得成員物件的內部實現細節對於新物件不可見,所以這種複用又稱為“黑箱”複用,相對繼承關係而言,其耦合度相對較低,成員物件的變化對新物件的影響不大,可以在新物件中根據實際需要有選擇性地呼叫成員物件的操作;合成複用可以在執行時動態進行,新物件可以動態地引用與成員物件型別相同的其他物件。

總之:如果兩個類之間是“Has-A”的關係應使用組合或聚合,如果是“Is-A”關係可使用繼承。在實現複用時應該多用關聯,少用繼承

文章http://www.uml.org.cn/sjms/201211023.asp中舉的粟子特別好,有有助於更好的理解!!!