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

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

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

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

軟件設計的七大原則
開閉原則(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)ide

不能存在多於一個致使類變動的緣由。舉個例子:一我的身兼數職,而這些事情相關性不大,甚至有衝突,那他就沒法很好的解決這些問題職責,應該分到不一樣的人身上去作。函數

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

里氏替換原則(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) ):儘可能使用組合和聚合,少使用繼承的關係來達到複用的原則。若是要使用繼承關係,則必須嚴格遵循里氏替換原則。合成複用原則同里氏替換原則相輔相成的,二者都是開閉原則的具體實現規範。

合成複用原則的重要性

一般類的複用分爲繼承複用和合成複用兩種,繼承複用雖然有簡單和易實現的優勢,但它也存在如下缺點。

繼承複用破壞了類的封裝性。由於繼承會將父類的實現細節暴露給子類,父類對子類是透明的,因此這種複用又稱爲「白箱」複用。

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

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

採用組合或聚合複用時,能夠將已有對象歸入新對象中,使之成爲新對象的一部分,新對象能夠調用已有對象的功能,它有如下優勢。

它維持了類的封裝性。由於成分對象的內部細節是新對象看不見的,因此這種複用又稱爲「黑箱」複用。

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

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

原文:https://www.zhoulujun.cn/html/theory/model/7824.html

相關文章
相關標籤/搜索