最少知識原則(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 University 的 Ian 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 方法僅能訪問以下這些類型的對象:
具體點兒就是,對象應儘量地避免調用由另外一個方法返回的對象的方法。
現代面向對象程序設計語言一般使用 "." 做爲訪問標識,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); }
上面這個設計有幾點問題:
除了上面這幾個問題以外,還有一個問題是這段代碼是可測試的嗎?你可能會說確定可測啊,由於這個類使用了依賴注入(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),這會提高類設計的複雜度。
參考資料