5 迪米特法則(Law Of Demeter)

2022-11-24 20:06:54 字數 2403 閱讀 5668

狹義的迪米特法則定義:也叫最少知識原則(lkp,least knowledge principle)。如果兩個類不必彼此直接通訊,那麼這兩個類就不應當發生直接的相互作用。如果其中的一個類需要呼叫另一個類的某一個方法的話,可以通過第三者**這個呼叫。

廣義的迪米特法則定義:一個模組設計得好壞的一個重要的標誌就是該模組在多大的程度上將自己的內部資料與實現有關的細節隱藏起來。資訊的隱藏非常重要的原因在於,它可以使各個子系統之間脫耦,從而允許它們獨立地被開發、優化、使用閱讀以及修改。

迪米特法則通常被表述為:only talk to your immediate friends ( 只和離你最近的朋友進行互動)。什麼是最近的朋友?我們知道,每個物件都會與其他物件之間有耦合關係,只要兩個物件之間有耦合關係,我們就說這兩個物件之間是朋友關係。耦合的方式很多,如依賴、關聯、組合、聚合等。其中,我們稱出現在成員變數、方法引數、方法返回值中的類為最近的朋友,而出現在區域性變數中的類則不是最近的朋友。迪米特法則是很好的解耦合手段之一。在網上看到的比較形象的說明這個法則的示例:

如果你想讓你的狗狗跑的話,你會對狗狗說還是對四條狗腿說?

如果你去店裡買東西,你會把錢交給店員,還是會把錢包交給店員讓他自己拿?

迪米特法則使物件之間的耦合降到最小,符合高內聚低耦合的特性,從而使得類具有很好的可讀性和可維護性。

後面介紹的設計模式中,外觀模式(facade)和中介者模式(mediator),都是迪米特法則應用的例子。

類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。

使用迪米特法則,降低類與類之間的耦合。

示例中有犯人、親人、獄友這些物件,接下來我就通過三個親人去監獄看犯人的設計來說明如何理解迪米特法則(該示例是從網上摘錄的,這裡使用swift語言進行重新編寫,並新增了uml圖來進行理解,最後用迪米特法則和依賴倒置原則相結合進行了擴充套件)。

設計1:親人和獄友有交流(違反迪米特法則,因為對於親人來說,獄友是陌生人)。

uml圖如下所示:

//

獄友class

inmates}//

犯人class

prisoners}//

家人class

family}//

呼叫let family =family();

family.visitprisoner(prisoners());

從上面可以看到,家人告訴犯人要與獄友好好相處,而獄友卻冒出來說話。這顯然越界了,因為監獄只允許家人探望犯人,而不是隨便誰都可以見。而家人和獄友有了溝通是違背迪米特法則的,所以我們需要將家人和獄友隔離開,對其進行重構。

設計2:家人和獄友沒有直接的交流。

uml圖如下所示:

//

獄友class

inmates}//

犯人class

prisoners}//

家人class

family}//

呼叫let family =family();

family.visitprisoner(prisoners());

設計3:和依賴倒置原則相結合。uml圖如下所示:

protocol inmatesdelegate

//獄友

class

inmates: inmatesdelegate}//

犯人class

prisoners}//

家人class

family}//

呼叫let family =family();

family.visitprisoner(prisoners(), inmates: inmates());

從上面看到,和依賴倒置原則相結合之後的設計,也是符合迪米特原則的:如果兩個類不必彼此直接通訊,那麼這兩個類就不應當發生直接的相互作用。如果其中的一個類需要呼叫另一個類的某一個方法的話,可以通過第三者**這個呼叫,這裡的第三者就是介面inmatesdelegate。大話設計模式那本書裡面介紹的小菜找it部修電腦的例子,也是迪米特原則和依賴倒置原則相結合的:在那個例子裡面,it部就是介面(類似這裡的inmatesdelegate),小張小李就是具體類(類似這裡的inmates),由於it部是抽象的,哪怕裡面的人都離職或換了新人,小菜的電腦出問題也還是可以找it部解決,而不需要認識其中的同事,純靠關係幫忙。