設計模式-----最少知識原則

最少知識原則

最少知識原則(Least Knowledge Principle), 最少知識原則(Least Knowledge Principle),或者稱迪米特法則(Law of Demeter),是一種面向對象程序設計的指導原則,它描述了一種保持代碼鬆耦合的策略。其可簡單的概括爲:html

Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.編程

每一個單元對其餘單元只擁有有限的知識,只瞭解與當前單元緊密聯繫的單元;app

再簡潔些:less

Each unit should only talk to its friends; don't talk to strangers.函數

每一個單元只能和它的 "朋友" 交談,不能和 "陌生人" 交談;測試

更簡潔些:設計

Only talk to your immediate friends.code

只和本身直接的 "朋友" 交談。orm

應用到面向對象的程序設計中時,可描述爲 "類應該與其協做類進行交互但無需瞭解它們的內部結構"。server

A class should interact directly with its collaborators and be shielded from understanding their internal structure.

迪米特法則(Law of Demeter)由 Northeastern UniversityIan Holland 在 1987 年提出,"Law of Demeter" 名稱是來自當時正在進行的一項研究 "The Demeter Project"。

Demeter = Greek Goddess of Agriculture; grow software in small steps.

在 2004 年,Karl Lieberherr 在其論文 "Controlling the Complexity of Software Designs" 中將 LoD 的定義由 "Only talk to your friends" 改進爲:

Only talk to your friends who share your concerns.

改進後的原則稱爲 LoDC(Law of Demeter for Concerns),它爲軟件設計帶來了兩個主要的益處:

It leads to better information hiding.

It leads to less information overload.

即,更好的信息隱藏和更少的信息重載。LoDC 原則在面向方面的軟件開發(AOSD:Aspect-Oriented Software Development)中有着良好的應用。

最少知識原則在面向對象編程中的應用

在 "Law of Demeter" 應用於面向對象編程中時,能夠簡稱爲 "LoD-F:Law of Demeter for Functions/Methods"。

對於對象 O 中的一個方法 m ,m 方法僅能訪問以下這些類型的對象:

  1. O 對象自身;
  2. m 方法的參數對象;
  3. 任何在 m 方法內建立的對象;
  4. O 對象直接依賴的對象;

具體點兒就是,對象應儘量地避免調用由另外一個方法返回的對象的方法。

現代面向對象程序設計語言一般使用 "." 做爲訪問標識,LoD 能夠被簡化爲 "僅使用一個點(use only one dot)"。也就是說,代碼 a.b.Method() 違反了 LoD,而 a.Method() 則符合 LoD。打個比方,人能夠命令一條狗行走,可是不該該直接指揮狗的腿行走,應該由狗去指揮它的腿行走。

你是否見過相似下面這樣兒的代碼?

public Emailer(Server server) {…} // taking a server in the constructor
public void sendSupportEmail(String message, String toAddress) {
    EmailSystem emailSystem = server.getEmailSystem();
    String fromAddress = emailSystem.getFromAddress();
    emailSystem.getSenderSubsystem().send(fromAddress, toAddress, message);
}

上面這個設計有幾點問題:

  1. 複雜並且看起來沒必要要。Emailer 與多個它可能不是真的須要的 API 進行交互,例如 EmailSystem。
  2. 依賴於 Server 和 EmailSystem 的內部結構,若是二者之一進行了修改,則 Emailer 有可能被破壞。
  3. 不能重用。任何其餘的 Server 實現也必須包含一個能返回 EmailSystem 的 API。

除了上面這幾個問題以外,還有一個問題是這段代碼是可測試的嗎?你可能會說確定可測啊,由於這個類使用了依賴注入(Dependency Injection),咱們能夠模擬 Server、EmailSystem 和 Sender 類。但真正的問題是,除了多出了這些模擬代碼,任何對 API 的修改都將破壞全部的測試用例,使得設計和測試都變得很是脆弱。

解決上述問題的辦法就是應用最少知識原則,僅經過構造函數注入直接依賴的對象。Emailer 無需瞭解是否 Server 類包含了一個 EmailSystem,也不知道 EmailSystem 包含了一個 Sender。

public Emailer(Sender sender, String fromAddress) {…}
public void sendSupportEmail(String message, String toAddress) {
    sender.send(fromAddress, toAddress, message);
}

這個設計較爲合理些。如今 Emailer 再也不依賴 Server 和 EmailSystem,而是經過構造函數獲得了全部的依賴項。同時 Emailer 也變得更容易理解,由於全部與其交互的對象都顯式的呈現出來。

Emailer 與 Server 和 EmailSystem 也達到了解耦合的效果。Emailer 再也不須要了解 Server 和 EmailSystem 的內部結構,任何對 Server 和 EmailSystem 的修改都再也不會影響 Emailer。

並且,Emailer 的變得更易被複用。若是切換到另一個環境中時,僅需實現一個不一樣的 Sender 便可。

對於測試而言,如今咱們僅需模擬 Sender 依賴便可。

應用最少知識原則優勢和缺點

優勢:遵照 Law of Demeter 將下降模塊間的耦合,提高了軟件的可維護性和可重用性。

缺點:應用 Law of Demeter 可能會致使不得不在類中設計出不少用於中轉的包裝方法(Wrapper Method),這會提高類設計的複雜度。

參考資料

相關文章
相關標籤/搜索