設計模式——面向對象的設計原則

shanzm-2020年3月31日 20:17:27

0. UML

統一建模語言(Unified Modeling Language,UML)是用來設計軟件藍圖的可視化建模語言。html

能夠參考統一建模語言編程

於此不詳述,僅展現使用Visual Studio自動生成的類圖樣式設計模式

須要說明的是,VS中生成的類圖樣式和通常通用的UML是有一些區別的,可是也就僅僅能夠稱之爲風格不一樣,其總體是同樣的架構

  • :藍色方框,上部分爲類名和該類的父類,下部分爲類中成員,抽象類類名爲斜體且方框爲虛線.net

    通用的UML中,訪問修飾符private(「-」),public(「+」),在VS中直接用單詞表示,無需多慮設計

  • 接口:綠色方框,上部分爲接口名,下部分爲接口成員(方法,屬性,事件)htm

  • 聚合關係:使用金色的實線加箭頭鏈接對象

    一個類中擁有另外一個類的類型的屬性,默認是顯示在屬性框中,右鍵->顯示爲關聯,則能夠顯示blog

  • 繼承關係:子類經過實線加箭頭指向父類繼承

  • 實現接口:實現類的上方使用實線鏈接一個圓形,並標註實現的接口名(這種表示方法稱之爲:棒棒糖表示法)

    通用的UML中,實現接口通常是使用虛線加箭頭指向接口

示例:

圖中描述的是:
Person類爲抽象類,有三個屬性,派生了Student類和Teacher類

ILivable爲接口,有兩個方法,Student和Teacher類都實現了該接口

Student類中有一個Teacher類型的屬性teacher,同時還有一個Class類型的屬性@class

Teacher類中有一個List<Student>類型的屬性students,同時還有一個Class類型的屬性@class

Class類中有List<Student>類型的屬性students,同時還有List<Teacher>類型的屬性teachers



1. 開閉原則

是什麼?
開閉原則(Open Closed Principle,OCP):軟件實體應該對擴展開放,對修改關閉。

即軟件實體儘可能在不修改軟件源代碼的狀況下進行擴展

這裏的軟件實體主要是指:模塊、類、接口、方法

它也是其餘面向對象設計原則的基礎,也是面向對象的程序設計的終極目標。

怎麼作?
在面向對象設計中,能夠經過「抽象約束、封裝變化」來實現開閉原則,即經過接口或者抽象類爲軟件實體定義一個相對穩定的抽象層,而將相同的可變因素封裝在相同的具體實現類中。

爲何?
當須要對軟件進行擴展的時候,咱們不須要修改抽象層,只須要從抽象類中派生一個實現類便可,從而實現軟件具備必定的穩定性和延續性。

開閉原則是面向對象程序設計的終極目標,而里氏轉換原則和依賴倒置原則都是實現開閉原則的方式。

這句話你品,你仔細品!



2. 里氏替換原則

是什麼?
里氏替換原則(Liskov Substitution Principle,LSP)父類對象出現的地方均可以使用子類對象替換。

換言之,一個父類對象引用能夠指向其子類對象。

怎麼實現一個父類對象引用能夠指向其子類對象呢?那就是遵循——子類能夠擴展父類的功能,可是不能改變(重寫)父類的原有功能

怎麼作?
運用里氏原則時,儘可能將須要擴展的類或是存在變化的類設計爲抽象類或是接口,並將其做爲基類使用,在編程的時候儘可能對基類對象進行編程。

爲何?
在程序中聲明基類引用,而該引用指向一個子類對象,這樣能夠隨時替換不一樣的子類對象,從而實現不一樣的功能,而不須要修改那些使用該基類對象的代碼。

以前說過,子類能夠擴展父類的功能,可是不要改變父類的原有功能,就是由於在調用一個父類對象中的方法使用,而此時我更換一個其子類對象,原則上是徹底能夠的,可是如果子類中對其父類中的方法重寫了,並且碰巧這裏調用這個父類中的方法,則程序會出現異常!



3. 依賴倒置原則

是什麼?
依賴倒置原則(Dependence Inversion Principle,DIP)高層模塊不該該依賴低層模塊,二者都應該依賴其抽象;抽象不該該依賴細節,細節應該依賴抽象。

怎麼作?
針對接口編程,而不是針對實現編程。

  • 每一個類儘可能提供接口或抽象類,或者二者都具有。
  • 變量的聲明類型儘可能是接口或者是抽象類
  • 任何類都不該該從具體類派生。
  • 使用繼承時儘可能遵循里氏替換原則。

爲何?
在軟件設計中,細節具備多變性,而抽象層則相對穩定,所以以抽象爲基礎搭建起來的架構要比以細節爲基礎搭建起來的架構要穩定得多。這裏的抽象指的是接口或者抽象類,而細節是指具體的實現類



4. 單一職責原則

是什麼?
單一職責原則(Single Responsibility Principle,SRP)又稱單一功能原則,一個類應該有且僅有一個引發它變化的緣由,不然類應該被拆分

換言之,一個類只負責一個功能領域中的相應職責

怎麼作?
發現並將類的不一樣職責分離,再封裝到不一樣的類或模塊中

爲何?
單一職責是實現高內聚,低耦合的指導方針

在面向對象的程序設計中,若是一個類承擔的職責越多,則其能夠被複用的可能性就越小。一個類承擔多個職責就是將多個職責耦合在一塊兒,當其中的一個職責發生改變的時候,可能會影響到其餘職責的功能。



5. 接口隔離原則

是什麼?
接口隔離原則(Interface Segregation Principle,ISP)將臃腫龐大的接口拆分紅更小的和更具體的接口,讓接口中只包含客戶感興趣的方法。

換言之,不要使用單一的總接口,使用具體的有針對性的小接口。

怎麼作?
接口儘可能要小,每一個接口承擔相對獨立的功能。

爲何?
面向對象中,實現一個接口,則必須實現接口中的全部方法,如果接口過於的龐大,則使用起來不方便,並且可能當前對象只須要該接口中的部分功能。



6. 迪米特法則

是什麼?
迪米特法則(Law of Demeter,LoD)又叫做最少知識原則(Least Knowledge Principle,LKP)「只與你的直接朋友交談,不跟'陌生人'說話」

換言之,一個軟件實體應當儘量少地與其餘實體發生相互做用。

其含義是:若是兩個軟件實體無須直接通訊,那麼就不該當發生直接的相互調用,能夠經過第三方轉發該調用。其目的是下降類之間的耦合度,提升模塊的相對獨立性。

怎麼作?

  1. 從依賴者的角度來講,只依賴應該依賴的對象。
  2. 從被依賴者的角度說,只暴露應該暴露的方法。

典型應用:中介者模式

爲何?
下降了類之間的耦合度,提升了模塊的相對獨立性,從而提升了類的可複用率和系統的擴展性。

可是嚴格的遵循迪米特法則,則可能會出現大量的中介者類,從而增長了系統的複雜性,下降了模塊之間通訊的效率。

因此採用迪米特法則須要權衡利弊,在確保低耦合的狀況下,避免增長系統的複雜性



7. 合成複用原則

是什麼?
合成複用原則(Composite Reuse Principle,CRP)它要求在軟件實體複用時,要儘可能先使用組合或者聚合等關聯關係來實現,其次才考慮使用繼承關係來實現。

換言之,儘可能使用對象組合,而不是使用繼承來達到複用的目的。

類與類之間的關係是一種結構性的關係,稱之爲關聯關係,包括:單項關聯,雙向關聯,自關聯,聚合關係,組合關係

  • 聚合關係:即部分與總體的關係(UML中使用空心的菱形表示),好比計算機包括鼠標,可是鼠標能夠單獨存在
  • 組合關係:也是部分與總體的關係,可是其中的部分與總體具備統一的生命週期(UML中使用實心黑色菱形表示),好比頭和嘴,沒有頭也就沒有了嘴

怎麼用?
合成複用原則是經過將已有的對象歸入新對象中,做爲新對象的成員對象來實現的,新對象能夠調用已有對象的功能,從而達到複用。

新對象經過委託的方式調用已有對象中的方法。(這也是委託的意義

爲何?
繼承關係破壞了類的封閉性,父類對子類是透明的,父類中的成員都暴露給子類(這種複用稱之爲「白箱」複用)

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



總結

  • 我我的以爲這些所謂的設計原則,包括全部的設計模式都是爲了如下目的:

    • 實現代碼模塊的解耦,實現高內聚,低耦合!----不要牽一髮而動全身

    • 加強代碼的可擴展性,實現程序的延續性!----不要沒法實現後續新需求

    • 提升代碼的魯棒性!----不要一修改,程序就崩潰

  • 7種設計原則總結

名稱 定義 使用頻率
開閉原則( Open Closed Principle,OCP ) 軟件實體應該對擴展開放,對修改關閉 ★★★★★
里氏替換原則(Liskov Substitution Principle,LSP) 父類對象出現的地方均可以使用子類對象替換 ★★★★★
依賴倒置原則(Dependence Inversion Principle,DIP) 高層模塊不該該依賴低層模塊,二者都應該依賴其抽象;抽象不該該依賴細節,細節應該依賴抽象 ★★★★★
單一職責原則(Single Responsibility Principle,SRP) 一個類只負責一個功能領域中的相應職責 ★★★★☆
接口隔離原則(Interface Segregation Principle ,ISP) 不要使用單一的總接口,而是使用具體的有針對性的小接口 ★★☆☆☆
迪米特法則(Law of Demeter, LoD) 一個軟件實體應當儘量少地與其餘實體發生相互做用 ★★★☆☆
合成複用原則(Composite Reuse Principle,CRP) 儘可能使用對象組合,而不是使用繼承來達到複用的目的 ★★★★☆

注:該表來源於《設計模式實訓教程(第二版)-劉偉》



參考

本文主要就是如下連接的閱讀筆記,詳細能夠閱讀如下內容:

C語言中文網:設計模式

《設計模式實訓教程(第二版)-劉偉》

相關文章
相關標籤/搜索