home > theory > model >

再談設計原則—7種設計原則學習總結筆記

author:[email protected]    hits:

由領域模型驅動軟件設計,用代碼來實現該領域模型;領域驅動設計告訴我們,在通過軟件實現一個業務系統時,建立一個領域模型是非常重要和必要的,因為領域模型具有以下特點:

這篇文章是對設計模式的再談系列總結性筆記,推薦閱讀C語言中文網上的《軟件設計模式概述

設計的根本目的是為了解決問題,解決問題的根本前提是要了解到都有哪些問題

可靠性/健壯性/可修改性/容易理解/程序簡便/可測試性/可擴展性/安全性

軟件設計的七大原則

開閉原則(OPEN CLOSE PRINCIPLE):一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉(Software entities should be open for extension,but closed for modification)。

目的就是保證程序的擴展性好,易于維護和升級。開閉原則被稱為面向對象設計的基石,實際上,其他原則都可以看作是實現開閉原則的工具和手段。意思就是:軟件對擴展應該是開放的,對修改是封閉的,通俗來說就是,開發一個軟件時,應該對其進行功能擴展,而在進行這些擴展時,不需要對原來的程序進行修改(不能去修改原有的代碼,而是要擴展原有代碼,實現一個熱插拔的效果)。

單一職責原則(Single-Responsibilitiy Principle)一個類負責一項職責,否則類應該被拆分(There should never be more than one reason for a class to change)

不能存在多于一個導致類變更的原因。舉個例子:一個人身兼數職,而這些事情相關性不大,甚至有沖突,那他就無法很好的解決這些問題職責,應該分到不同的人身上去做。

單一職責原則是實現高內聚低耦合的最好方法,沒有之一

里氏替換原則(Liskov Substitution Principle):繼承必須確保超類所擁有的性質在子類中仍然成立(Inheritance should ensure that any property proved about supertype objects also holds for subtype objects)

繼承與派生的規則:子類可以擴展父類的功能,但是不能改變父類原有的功能。也就是說:子類繼承父類時,除添加新的方法完成新增功能外,盡量不要重寫父類的方法。任何基類可以出現的地方,子類一定可以出現。它克服了繼承中重寫父類造成的可復用性變差的缺點。確保類的擴展不會給已有的系統引入新的錯誤,降低了代碼出錯的可能性

實現開閉原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。向上轉型是Java的基礎,我們經常也用到,實際上,在進行設計的時候,盡量從抽象類繼承,而不是從具體類繼承。同時,保證在軟件系統中,把父類都替換成它的子類,程序的行為沒有變化,就足夠了。

LSP是繼承復用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。

依賴倒置原則(Dependence Inversion Principle):高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象(High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions)。

依賴倒置原則是實現開閉原則的重要途徑之一,它降低了客戶與實現模塊之間的耦合。

其核心思想是:要面向接口編程,不要面向實現編程。即依賴于抽象而不依賴于具體。這個是開閉原則的基礎。高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。寫代碼時用到具體類時,不與具體類交互,而與具體類的上層接口交互。依賴倒置原則的目的是通過要面向接口的編程來降低類間的耦合性,其需要遵從的規則:

  • 每個類盡量提供接口或抽象類,或者兩者都具備。

  • 變量的聲明類型盡量是接口或者是抽象類。

  • 任何類都不應該從具體類派生。

  • 使用繼承時盡量遵循里氏替換原則。

接口隔離原則(Interface Segregation Principle): 一個類對另一個類的依賴應該建立在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface)。即:建立單一接口,不要建立龐大臃腫的接口,盡量細化接口,接口中的方法盡量少。該原則還有另外一個定義:客戶端不應該被迫依賴于它不使用的方法(Clients should not be forced to depend on methods they do not use)。以上兩個定義的含義是:要為各個類建立它們需要的專用接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用。

這個原則的意思是:每個接口中不存在子類用不到卻必須實現的方法,如果不然,就要將接口拆分使用多個隔離的接口,比使用單個接口(多個接口方法集合到一個的接口)要好

接口隔離原則和單一職責都是為了提高類的內聚性、降低它們之間的耦合性,體現了封裝的思想,但兩者是不同的:

  • 單一職責原則注重的是職責,而接口隔離原則注重的是對接口依賴的隔離。

  • 單一職責原則主要是約束類,它針對的是程序中的實現和細節;接口隔離原則主要約束接口,主要針對抽象和程序整體框架的構建。

在具體應用接口隔離原則時,應該根據以下幾個規則來衡量。

  • 接口盡量小,但是要有限度。一個接口只服務于一個子模塊或業務邏輯。

  • 為依賴接口的類定制服務。只提供調用者需要的方法,屏蔽不需要的方法。

  • 了解環境,拒絕盲從。每個項目或產品都有選定的環境因素,環境不同,接口拆分的標準就不同深入了解業務邏輯。

  • 提高內聚,減少對外交互。使接口用最少的方法去完成最多的事情。

迪米特法則||最少知道原則(Low of Demeter Principle||Least Knowledge Principle):只與你的直接朋友交談,不跟“陌生人”說話(Talk only to your immediate friends and not to strangers)。其含義是:如果兩個軟件實體無須直接通信,那么就不應當發生直接的相互調用,可以通過第三方轉發該調用。其目的是降低類之間的耦合度,提高模塊的相對獨立性(低耦合,高內聚)。

就是說:一個類對自己依賴的類知道的越少越好(黑盒模式)。也就是說無論被依賴的類多么復雜,都應該將邏輯封裝在方法的內部,通過public方法提供給外部。這樣當被依賴的類變化時,才能最小的影響該類。

只與直接的朋友通信(類之間只要有耦合關系,就叫朋友關系)。耦合分為依賴、關聯、聚合、組合等。我們稱出現為成員變量、方法參數、方法返回值中的類為直接朋友。局部變量、臨時變量則不是直接的朋友。我們要求陌生的類不要作為局部變量出現在類中。

在運用迪米特法則時要注意以下 6 點。

  • 在類的劃分上,應該創建弱耦合的類。類與類之間的耦合越弱,就越有利于實現可復用的目標。

  • 在類的結構設計上,盡量降低類成員的訪問權限。

  • 在類的設計上,優先考慮將一個類設置成不變類。

  • 在對其他類的引用上,將引用其他對象的次數降到最低。

  • 不暴露類的屬性成員,而應該提供相應的訪問器(set 和 get 方法)。

  • 謹慎使用序列化(Serializable)功能

組合||聚合||合成復用原則(Composition/Aggregation Reuse Principle(CARP) )盡量使用組合和聚合,少使用繼承的關系來達到復用的原則。如果要使用繼承關系,則必須嚴格遵循里氏替換原則。合成復用原則同里氏替換原則相輔相成的,兩者都是開閉原則的具體實現規范。

合成復用原則的重要性

通常類的復用分為繼承復用和合成復用兩種,繼承復用雖然有簡單和易實現的優點,但它也存在以下缺點。

  • 繼承復用破壞了類的封裝性。因為繼承會將父類的實現細節暴露給子類,父類對子類是透明的,所以這種復用又稱為“白箱”復用。

  • 子類與父類的耦合度高。父類的實現的任何改變都會導致子類的實現發生變化,這不利于類的擴展與維護。

  • 它限制了復用的靈活性。從父類繼承而來的實現是靜態的,在編譯時已經定義,所以在運行時不可能發生變化。


采用組合或聚合復用時,可以將已有對象納入新對象中,使之成為新對象的一部分,新對象可以調用已有對象的功能,它有以下優點。

  • 它維持了類的封裝性。因為成分對象的內部細節是新對象看不見的,所以這種復用又稱為“黑箱”復用。

  • 新舊類之間的耦合度低。這種復用所需的依賴較少,新對象存取成分對象的唯一方法是通過成分對象的接口。

  • 復用的靈活性高。這種復用可以在運行時動態進行,新對象可以動態地引用與成分對象類型相同的對象。


轉載本站文章《再談設計原則—7種設計原則學習總結筆記》, 請注明出處:http://www.qsexmk.tw/html/theory/model/7824.html