設計模式六大原則 - 迪米特法則

VonB54 8年前發布 | 6K 次閱讀 迪米特法則

迪米特法則有很多種說法,比如:一個類應該應該對其他類盡可能了解得最少;類只與直接的朋友通信等等。但是其最終目的只有一個,就是讓類間解耦。

定義

迪米特法則:Law Of Demeter,LoD。

也被稱為最少知識原則,Least Knowledge Principle,LKP。

就是說一個對象應該對其他對象保持最少的了解。正如最少知識原則這個定義一樣,一個類應該對其耦合的其他類或所調用的類知道得最少。所耦合的類內部無論如何復雜,怎么實現的我都不需要知道,我只調用你public出來的這些方法,其他都不用知道。

另外可以解釋一下開頭提到的只與直接的朋友通信,什么叫直接的朋友呢?我們繼續看。

舉個例子

光看定義可能無法完全理解它所表達的含義,以及在什么場景下才需要使用這個迪米特法則。現在我們就來舉個“栗子”。

現在市面上各種人脈書上很多都會提到“六度人脈”這個理論,這個理論說的是你與世界上任何一個人中間只隔了六個人。也就是說你想找任何一個人,無論這個人是政界要人,還是商界巨鱷,抑或是明星名人,你最多只通過六個人就可以聯系到他(想想還有點小激動呢-_-#)。

我們暫且不論這個理論是對是錯,在現實生活中我們也經常遇到這樣的情況。比如你想辦一件事情,但是憑借你的能力是做不到的,而你周圍的朋友也無法幫你辦到。但是恰好你有一個朋友認識有另外一個朋友可以辦得成此事,那么你只有拜托你這位朋友中間牽線搭橋,讓他的朋友幫你辦好此事。

在這個例子中,我們就暫且定義你為A,你的朋友為B,你朋友的朋友為C好了。

反面教材

我們先來看看表達此種關系的UML類圖:

實現代碼如下:

1.類A和類B是好朋友,能找到類B來幫忙:

public classA{

    public String name;

    publicA(String name){
        this.name = name;
    }

    publicBgetB(String name){
        return new B(name);
    }

    publicvoidwork(){
        B b = getB("李四");
        C c = b.getC("王五");
        c.work();
    }
}

2.類B和類C是好朋友,能知道類C來幫忙:

public classB{

    private String name;

    publicB(String name){
        this.name = name;
    }

    publicCgetC(String name){
        return new C(name);
    }
}

3.類C能夠辦成此事:

public classC{

    public String name;

    publicC(String name){
        this.name = name;
    }

    publicvoidwork(){
        System.out.println(name + "把這件事做好了");
    }
}

4.場景類

public classClient{
    publicstaticvoidmain(String[] args){
        A a = new A("張三");
        a.work();
    }
}

運行結果如下:

王五把這件事做好了

上面的輸出雖然是把事情成功辦好了,但是仔細看業務邏輯明顯是不對的。A和C又不是好朋友,為什么在類A中會出現類C呢?他們又互相不認識。

看到這里很多人都會明白,這種場景在實際開發中是非常常見的一種情況。對象A需要調用對象B的方法,對象B有需要調用對象C的方法……就是常見的getXXX().getXXX().getXXX()……類似于這種代碼。如果你發現你的代碼中也有這樣的代碼,那就考慮下是不是違反迪米特法則,是不是要重構一下了。

正確例子

為了符合迪米特法則,也為了讓業務邏輯能夠說得通,我們把上面的例子稍微修改一下。

UML類圖如下:

代碼如下:

1.類A和類B是好朋友,能找到類B來幫忙:

public classA{

    public String name;

    publicA(String name){
        this.name = name;
    }

    publicBgetB(String name){
        return new B(name);
    }

    publicvoidwork(){
        B b = getB("李四");
        b.work();
    }
}

2.類B和類C是好朋友,能知道類C來幫忙:

public classB{

    private String name;

    publicB(String name){
        this.name = name;
    }

    publicCgetC(String name){
        return new C(name);
    }

    publicvoidwork(){
        C c = getC("王五");
        c.work();
    }
}

3.類C能夠辦成此事:

public classC{

    public String name;

    publicC(String name){
        this.name = name;
    }

    publicvoidwork(){
        System.out.println(name + "把這件事做好了");
    }
}

4.場景類

public classClient{
    publicstaticvoidmain(String[] args){
        A a = new A("張三");
        a.work();
    }
}

運行結果如下:

王五把這件事做好了

上面代碼只是修改了下類A和B的work方法,使之符合了迪米特法則:

  • 類A只與最直接的朋友類B通信,不與類C通信;
  • 類A只調用類B提供的方法即可,不用關心類B內部是如何實現的(至于B是怎么調用的C,這些A都不用關心)。

總結

迪米特法則的目的是讓類之間解耦,降低耦合度。只有這樣,類的可復用性才能提高。

但是迪米特法則也有弊端,它會產生大量的中轉類或跳轉類,導致系統的復雜度提高。

所以我們不要太死板的遵守這個迪米特法則,在系統設計的時候,在弱耦合和結構清晰之間反復權衡。盡量保證系統結構清晰,又能做到低耦合。

 

 

來自:https://tianweili.github.io/2015/02/12/設計模式六大原則-迪米特法則/

 

 本文由用戶 VonB54 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!