文章出處

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

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

每個單元對其他單元只擁有有限的知識,只了解與當前單元緊密聯系的單元;

再簡潔些:

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

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

更簡潔些:

Only talk to your immediate friends.

只和自己直接的 "朋友" 交談。

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

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。打個比方,人可以命令一條狗行走,但是不應該直接指揮狗的腿行走,應該由狗去指揮它的腿行走。

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

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

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

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

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

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

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

這個設計較為合理些。現在 Emailer 不再依賴 Server 和 EmailSystem,而是通過構造函數得到了所有的依賴項。同時 Emailer 也變得更容易理解,因為所有與其交互的對象都顯式的呈現出來。

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

而且,Emailer 的變得更易被復用。如果切換到另外一個環境中時,僅需實現一個不同的 Sender 即可。

對于測試而言,現在我們僅需模擬 Sender 依賴即可。

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

優點:遵守 Law of Demeter 將降低模塊間的耦合,提升了軟件的可維護性和可重用性。

缺點:應用 Law of Demeter 可能會導致不得不在類中設計出很多用于中轉的包裝方法(Wrapper Method),這會提升類設計的復雜度。

 

面向對象設計的原則

 SRP

 單一職責原則

 Single Responsibility Principle

 OCP

 開放封閉原則

 Open Closed Principle

 LSP

 里氏替換原則

 Liskov Substitution Principle

 ISP

 接口分離原則

 Interface Segregation Principle

 DIP

 依賴倒置原則

 Dependency Inversion Principle

 LKP

 最少知識原則

 Least Knowledge Principle

參考資料

 

本文《最少知識原則(Least Knowledge Principle)》由 Dennis Gao 原創并發表自博客園,未經作者本人同意禁止任何形式的轉載,任何自動或人為的爬蟲行為均為耍流氓。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()