天天看點

Unity_面向對象設計原則_026

單一原則SRP

單一職責原則是最簡單的面向對象設計原則,用于控制類的粒度大小

單一職責原則:一個對象應該隻包含單一的職責,并且該職責被完整地封裝在一個類中。

就一個類而言,應該僅有一個引起它變化的原因

一個類(大到子產品,小到方法)承擔的職責越多,它被複用的可能性就越小

當一個職責變化時,可能會影響其他職責的運作

将這些職責進行分離,将不同的職責封裝在不同的類中

将不同的變化原因封裝在不同的類中

單一職責原則是實作高内聚、低耦合的指導方針

如果一個類承擔的職責過多,就等于把這些職責耦合在一起,一個職責的變化可能會削弱或者抑制這個類完成其他職責的能力。這種耦合會導緻脆弱的設計,當變化發生時,設計會遭受到意向不到的破壞。

開閉原則OCP

開閉原則是面向對象的可複用設計的第一塊基石,是最重要的面向對象設計原則

開閉原則:軟體實體應當對擴充開放,對修改關閉。

開閉原則由Bertrand Meyer于1988年提出

在開閉原則的定義中,軟體實體可以是一個軟體子產品、一個由多個類組成的局部結構或一個獨立的類

開閉原則是指軟體實體應盡量在不修改原有代碼的情況下進行擴充

抽象化是開閉原則的關鍵

相對穩定的抽象層 + 靈活的具體層

對可變性封裝原則(Principle of Encapsulation of Variation, EVP):在你的設計中什麼可能會發生變化,應使之成為抽象層而封裝,而不是什麼會導緻設計改變才封裝

一個軟體實體應當對擴充開放,對修改關閉,也就是說在設計一個子產品的時候,應當使這個子產品可以在部内修改的前提下被擴充,即實作在不修改源代碼的情況下改變這個子產品的行為。

開閉原則面對需求,對程式的改動是通過增加新的代碼來進行的,而不是改變原來的代碼。(接口比較友善)

裡氏轉換原則LSP

子類必須能夠替換掉他們的父類。

裡氏代換原則:所有引用基類的地方必須能透明地使用其子類的對象。

子類可以擴充父類的功能,但不能改變父類原有的功能

裡氏代換原則由2008年圖靈獎得主、美國第一位計算機科學女博士、麻省理工學院教授Barbara Liskov和卡内基.梅隆大學Jeannette Wing教授于1994年提出

在軟體中将一個基類對象替換成它的子類對象,程式将不會産生任何錯誤和異常,反過來則不成立。如果一個軟體實體使用的是一個子類對象的話,那麼它不一定能夠使用基類對象

在程式中盡量使用基類類型來對對象進行定義,而在運作時再确定其子類類型

我喜歡動物

我喜歡狗

因為狗是動物

依賴倒置原則DIP

高層子產品不應該依賴底層子產品,它們都應該依賴抽象,抽象不應該依賴于細節,細節應該依賴于抽象

要針對接口程式設計,不要針對于實作程式設計

依賴倒轉原則:

A:高層子產品不應該依賴低層子產品,它們都應該依賴抽象。

B:抽象不應該依賴于細節,細節應該依賴于抽象。

要針對接口程式設計,不要針對實作程式設計

依賴倒轉原則是Robert C. Martin在1996年為“C++ Reporter”所寫的專欄Engineering Notebook的第三篇,後來加入到他在2002年出版的經典著作《Agile Software Development, Principles, Patterns, and Practices》一書中

在程式代碼中傳遞參數時或在關聯關系中,盡量引用層次高的抽象層類,即使用接口和抽象類進行變量類型聲明、參數類型聲明、方法傳回類型聲明,以及資料類型的轉換等

在程式中盡量使用抽象層進行程式設計,而将具體類寫在配置檔案中

針對抽象層程式設計,将具體類的對象通過依賴注入(Dependency Injection, DI)的方式注入到其他對象

構造注入

設值注入(Setter注入)

接口注入

接口隔離原則ISP

接口隔離原則:用戶端不應該依賴那些它不需要的接口。

當一個接口太大時,需要将它分割成一些更細小的接口

使用該接口的用戶端僅需知道與之相關的方法即可

每一個接口應該承擔一種相對獨立的角色,不幹不該幹的事,該幹的事都要幹

“接口”定義(1):一個類型所提供的所有方法特征的集合。一個接口代表一個角色,每個角色都有它特定的一個接口,“角色隔離原則”

“接口”定義(2):狹義的特定語言的接口。接口僅僅提供用戶端需要的行為,用戶端不需要的行為則隐藏起來,應當為用戶端提供盡可能小的單獨的接口,而不要提供大的總接口,每個接口中隻包含一個用戶端所需的方法,“定制服務”

合成複用原則CRP

合成複用原則:優先使用對象組合,而不是繼承來達到複用的目的。

合成複用原則就是在一個新的對象裡通過關聯關系(包括組合關系和聚合關系)來使用一些已有的對象,使之成為新對象的一部分

新對象通過委派調用已有對象的方法達到複用功能的目的

複用時要盡量使用組合/聚合關系(關聯關系),少用繼承

合成或組合(Composition)是一種強的擁有關系,展現了嚴格的部分和整體關系,部分和整體的生命周期是保持一緻的

聚合(Aggregation)是一種弱的擁有關系,展現的是A對象可以包含B對象,但B對象不是A對象的一部分。

個人的了解

合成的例子:大雁與大雁的翅膀,二者公存亡。比聚合的耦合關系更加強烈

聚合的例子:大雁與雁群,二者生命周期并不一緻。

繼承複用:實作簡單,易于擴充。破壞系統的封裝性;從基類繼承而來的實作是靜态的,不可能在運作時發生改變,沒有足夠的靈活性;隻能在有限的環境中使用。(“白箱”複用 )

組合/聚合複用:耦合度相對較低,有選擇性地調用成員對象的操作;可以在運作時動态進行,新對象可以動态地引用與成員對象類型相同的其他對象。(“黑箱”複用 )

迪米特法則LKP

迪米特法則又稱為最少知識原則(Least Knowledge Principle, LKP)

迪米特法則:每一個軟體機關對其他的機關都隻有最少的知識,而且局限于那些與本機關密切相關的軟體機關。

迪米特法則來自于1987年美國東北大學(Northeastern University)一個名為“Demeter”的研究項目

迪米特法則要求一個軟體實體應當盡可能少地與其他實體發生互相作用

應用迪米特法則可降低系統的耦合度,使類與類之間保持松散的耦合關系

不要和“陌生人”說話 (Don’t talk to strangers.)

隻與你的直接朋友通信 (Talk only to your immediate friends.)

(1) 目前對象本身(this)

(2) 以參數形式傳入到目前對象方法中的對象

(3) 目前對象的成員對象

(4) 如果目前對象的成員對象是一個集合,那麼集合中的元素也都是朋友

(5) 目前對象所建立的對象

任何一個對象,如果滿足上面的條件之一,就是目前對象的“朋友”,否則就是“陌生人”

在應用迪米特法則時,一個對象隻能與直接朋友發生互動,不要和“陌生人”發生直接互動,這樣做可以降低系統的耦合度,一個對象的改變不會給太多其他對象帶來影響

迪米特法則要求在設計系統時,應該盡量減少對象之間的互動

如果兩個對象之間不必彼此直接通信,那麼這兩個對象就不應該發生任何直接的互相作用

如果其中一個對象需要調用另一個對象的方法,可以通過“第三者”轉發這個調用

通過引入一個合理的“第三者”來降低現有對象之間的耦合度

應用迪米特法則注意點:

在類的劃分上,應當盡量建立松耦合的類,類之間的耦合度越低,越有利于複用,一個處在松耦合中的類一旦被修改,不會對關聯的類造成太大影響

在類的結構設計上,每一個類都應當盡量降低其成員變量和成員函數的通路權限

在類的設計上,隻要有可能,一個類型應當設計成不變類

在對其他類的引用上,一個對象對其他對象的引用應當降到最低

上述原則的作用:讓自己設計實作出來的軟體系統更加穩定,容易維護,并具有一緻性。

繼續閱讀