1. 程式人生 > 其它 >迪米特法則

迪米特法則

迪米特法則的定義

迪米特法則(Law of Demeter,LoD)又叫作最少知識原則(Least Knowledge Principle,LKP),產生於 1987 年美國東北大學(Northeastern University)的一個名為迪米特(Demeter)的研究專案,由伊恩·荷蘭(Ian Holland)提出,被 UML 創始者之一的布奇(Booch)普及,後來又因為在經典著作《程式設計師修煉之道》(The Pragmatic Programmer)提及而廣為人知。

迪米特法則的定義是:只與你的直接朋友交談,不跟“陌生人”說話(Talk only to your immediate friends and not to strangers)。其含義是:如果兩個軟體實體無須直接通訊,那麼就不應當發生直接的相互呼叫,可以通過第三方轉發該呼叫。其目的是降低類之間的耦合度,提高模組的相對獨立性。

迪米特法則中的“朋友”是指:當前物件本身、當前物件的成員物件、當前物件所建立的物件、當前物件的方法引數等,這些物件同當前物件存在關聯、聚合或組合關係,可以直接訪問這些物件的方法。

迪米特法則的優點

迪米特法則要求限制軟體實體之間通訊的寬度和深度,正確使用迪米特法則將有以下兩個優點。

  1. 降低了類之間的耦合度,提高了模組的相對獨立性。
  2. 由於親合度降低,從而提高了類的可複用率和系統的擴充套件性。


但是,過度使用迪米特法則會使系統產生大量的中介類,從而增加系統的複雜性,使模組之間的通訊效率降低。所以,在釆用迪米特法則時需要反覆權衡,確保高內聚和低耦合的同時,保證系統的結構清晰。

迪米特法則的實現方法

從迪米特法則的定義和特點可知,它強調以下兩點:

  1. 從依賴者的角度來說,只依賴應該依賴的物件。
  2. 從被依賴者的角度說,只暴露應該暴露的方法。


所以,在運用迪米特法則時要注意以下 6 點。

  1. 在類的劃分上,應該建立弱耦合的類。類與類之間的耦合越弱,就越有利於實現可複用的目標。
  2. 在類的結構設計上,儘量降低類成員的訪問許可權。
  3. 在類的設計上,優先考慮將一個類設定成不變類。
  4. 在對其他類的引用上,將引用其他物件的次數降到最低。
  5. 不暴露類的屬性成員,而應該提供相應的訪問器(set 和 get 方法)。
  6. 謹慎使用序列化(Serializable)功能。


【例1】明星與經紀人的關係例項。

分析:明星由於全身心投入藝術,所以許多日常事務由經紀人負責處理,如與粉絲的見面會,與媒體公司的業務洽淡等。這裡的經紀人是明星的朋友,而粉絲和媒體公司是陌生人,所以適合使用迪米特法則,其類圖如圖 1 所示。

程式程式碼如下:

package principle;
public class LoDtest {
    public static void main(String[] args) {
        Agent agent = new Agent();
        agent.setStar(new Star("林心如"));
        agent.setFans(new Fans("粉絲韓丞"));
        agent.setCompany(new Company("中國傳媒有限公司"));
        agent.meeting();
        agent.business();
    }
}
//經紀人
class Agent {
    private Star myStar;
    private Fans myFans;
    private Company myCompany;
    public void setStar(Star myStar) {
        this.myStar = myStar;
    }
    public void setFans(Fans myFans) {
        this.myFans = myFans;
    }
    public void setCompany(Company myCompany) {
        this.myCompany = myCompany;
    }
    public void meeting() {
        System.out.println(myFans.getName() + "與明星" + myStar.getName() + "見面了。");
    }
    public void business() {
        System.out.println(myCompany.getName() + "與明星" + myStar.getName() + "洽淡業務。");
    }
}
//明星
class Star {
    private String name;
    Star(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
//粉絲
class Fans {
    private String name;
    Fans(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
//媒體公司
class Company {
    private String name;
    Company(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

程式的執行結果如下:

粉絲韓丞與明星林心如見面了。
中國傳媒有限公司與明星林心如洽淡業務。