天天看點

面向對象設計原則(三)6. 合成複用原則7. 迪米特原則

合成複用原則又稱為聚合複用原則(Composition/Aggregate Reuse Principle, CARP), 其定義如下:

合成複用原則(Composite Reuse Principle, CRP): 盡量使用對象組合, 而不是繼承來達到複用的目的

迪米特法則(Law of Demeter, LoD):一個軟體實體應當盡可能少地與其他實體發生互相作用。

在迪米特法則運用系統設計中時, 要注意下面的幾點, 在類的劃分是上, 應當盡量建立松耦合類, 類之間的耦合度越低 就越有利于複用, 一個出在松耦合類一旦被修改, 不會對關聯的類造成太大波及; 在類的結構設計上, 每一個類都應當盡量降低其成員變量和成員函數的通路權限; 在類的設計上, 隻要有可能, 一個類型應當設計成不變類; 在對其他類的應用上, 一個對象對其他對象的引用應當降到最低.

迪米特法則要求我們在設計系統時, 應該盡量減少對象之間的互動, 如果兩個對象之間不必彼此直接通信, 那麼這兩個對象就不應當發生任何至二級的互相作用, 如果其中也給對象需要調用另外一個對象的某一個方法的話, 可以通過第三者轉發這個調用, 簡言之. 就是通過引用一個合理的第三者來降低現有對象之間的耦合度

以上的任何一個對象, 都可以當成目前對象的朋友, 否則就是"陌生人", 在應用迪米特法則時, 一個對象隻能與至二級朋友發生互動, 不要與"陌生人"直接互動, 這樣做可以降低系統的耦合度, 一個對象的改變不會給太多其他對象帶來影響

目前對下你給自身(this)

以參數形式傳入傳入到對象中

目前對象的成員對象

目前對象鎖建立的對象

迪米特原則嗨喲集中定義形式: 包括: 不要和"陌生人"說話, 隻與你的直接朋友通信等, 子迪米特法則中, 對于一個對象, 其朋友包括以下幾類:

如果一個系統符合迪米特法則,那麼當其中某一個子產品發生修改時,就會盡量少地影響其他子產品,擴充會相對容易,這是對軟體實體之間通信的限制,迪米特法則要求限制軟體實體之間通信的寬度和深度。迪米特原則可降低系統的耦合度, 使類與類之間保持松散的耦合關系.

迪米特法則來自于1987年美國東北大學(Northeastern University)一個名為“Demeter”的研究項目。迪米特法 則又稱為最少知識原則(LeastKnowledge Principle, LKP),其定義如下:

一般而言,如果兩個類之間是“Has-A”的關系應使用組合或聚合,如果是“Is-A”關系可使用繼承。"Is-A"是嚴格的分類學意義上的定義,意思是一個類是另一個類的"一種";而"Has-A"則不同,它表示某一個角色具有某一項責 任。

由于組合或聚合關系可以将已有的對象(也可稱為成員對象)納入到新對象中,使之成為新對象的一部分,是以新對象可以調用已有對象的功能,這樣做可以使得成員對象的内部實作細節對于新對象不可見,是以這種複用又稱為“黑箱”複用,相對繼承關系而言,其耦合度相對較低,成員對象的變化對新對象的影響不大,可以在新對象中根據實際需要有選擇性地調用成員對象的操作;合成複用可以在運作時動态進行,新對象可以動态地引用與成員對象類型相同的其他對象。

通過繼承來進行複用的主要問題在于繼承複用會破壞系統的封裝性,因為繼承會将基類的實作細節暴露給子類,由于基類的内部細節通常對子類來說是可見的,是以這種複用又稱“白箱”複用,如果基類發生改變,那麼子類的實也不得不發生改變;從基類繼承而來的實作是靜态的,不可能在運作時發生改變,沒有足夠的靈活性;而且繼承隻能在有限的環境中使用(如類沒有聲明為不能被繼承)。

在面向對象設計中, 可以通過兩種方法在不同的環境中複用已有的設計和實作, 即通過組合/聚合或通過繼承, 但首先應該考慮使用組合/聚合, 組合/聚合可以使系統更加靈活, 降低類與類之間的耦合度, 一個類的變化對其他類造成的影響相對較少; 其次才考慮繼承, 使用繼承時, 需要嚴格遵循裡式替換原則, 有效使用繼承會有助于對問題的了解 降低複雜度, 而濫用繼承反而會增阿系統建構和維護的難度以及系統的複雜度 是以需要慎重使用繼承複用

合成複用原則就是在一個新的對象裡通過關聯關系(包括組合關系和聚合關系)來使用一些已有的對象, 使之成為新對象的一部分, 新對象通過委派調用已有對象的方法達到複用功能的目的. 簡言之: 複用時要盡量使用組合/聚合關系, 少用繼承.