欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java面向?qū)ο笤O(shè)計原則之迪米特法則介紹

 更新時間:2023年02月14日 10:18:05   作者:每天都要進步一點點  
迪米特法則解決類與類之間耦合度問題,如果類A調(diào)用了B類的某一個方法,則這兩個類就形成了一種緊耦合的方式,當(dāng)B類這個方法發(fā)生變化時,一定會影響A類的執(zhí)行結(jié)果。迪米特法則要求每一個類盡可能少的與其他類發(fā)生關(guān)系

一、迪米特法則的定義

迪米特法則,也稱為最少知識原則,雖然名字不同,但描述的是同一個規(guī)則:一個對象應(yīng)該對其他對象有最少的了解。通俗地講,一個類應(yīng)該對自己需要耦合或調(diào)用的類知道得最少,被耦合或調(diào)用的類的內(nèi)部是如何復(fù)雜都和我沒關(guān)系,我就知道你提供的這么多public方法,我就調(diào)用這么多,其他的我一概不關(guān)心。

二、迪米特法則的含義

迪米特法則對類的低耦合提出了明確的規(guī)定,其包含以下幾層含義。

(一)、只和朋友交流

迪米特法則,要求只與直接朋友通信。什么叫直接朋友?每個對象都必然會與其他對象有耦合關(guān)系,兩個對象之間的耦合就成為朋友關(guān)系,這種關(guān)系的類型有很多,例如組合、聚合、依賴等。下面我們舉例說明如何才能做到只與直接朋友進行交流。

舉例:老師讓體育委員確認(rèn)一下全班女生是否都到齊?類圖如下圖所示:

其實現(xiàn)過程如下代碼:

老師類:

public class Teacher {
    //老師發(fā)出命令,清點一下女生人數(shù)
    public void command(GroupLeader groupLeader) {
        List<Girl> girls = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            girls.add(new Girl());
        }
        //告訴體育委員開始執(zhí)行清查任務(wù)
        groupLeader.countGirls(girls);
    }
}

老師只有一個方法command,先定義出所有的女生,然后發(fā)布命令給體育委員,去清點女生的人數(shù)。

體育委員GroupLeader的代碼如下:

public class GroupLeader {
    public void countGirls(List<Girl> girlList) {
        System.out.println("女生數(shù)量: " + girlList.size());
    }
}

老師類和體育委員類都對Girl類產(chǎn)生依賴,而且女生類不需要執(zhí)行任何動作,因此定義如下:

public class Girl {
}

再定義一個場景類:

public class Client {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.command(new GroupLeader());
    }
}

運行結(jié)果如下:

女生數(shù)量: 10

體育委員按照老師的要求對女生進行了清點,并得出了數(shù)量。我們回過頭來思考一下這個程序有什么問題,首先確定Teacher類有幾個朋友類,它僅有一個朋友類-------GroupLeader,為什么Girl不是朋友類呢?Teacher對Girl類產(chǎn)生了依賴啊,朋友類的定義是這樣的:出現(xiàn)在成員變量、方法的輸入?yún)?shù)、輸出參數(shù)中的類成為成員朋友類。而Gril這個類是出現(xiàn)在command方法內(nèi)部的,因此不屬于Teacher的直接朋友。

迪米特法則告訴我們一個類只與朋友類交流,但是我們剛剛定義的command方法卻與Girl類有了交流,聲明了List<Girl>動態(tài)集合,這樣就破壞了Teacher的健壯性。

問題已經(jīng)發(fā)現(xiàn),我們修改一下程序,將類圖稍作調(diào)整,如下圖所示:

修改后的老師類:

public class Teacher {
    //老師發(fā)出命令,清點一下女生人數(shù)
    public void command(GroupLeader groupLeader) {
        //告訴體育委員開始執(zhí)行清查任務(wù)
        groupLeader.countGirls();
    }
}

修改后的GroupLeader體育委員類:

public class GroupLeader {
    private List<Girl> girls;
    public GroupLeader(List<Girl> girls) {
        this.girls = girls;
    }
    public void countGirls() {
        System.out.println("女生數(shù)量: " + girls.size());
    }
}

在GroupLeader類中定義了一個構(gòu)造函數(shù),通過構(gòu)造函數(shù)傳遞了依賴關(guān)系。同時,對場景類也進行了一些調(diào)整:

public class Client {
    public static void main(String[] args) {
        List<Girl> girls = new ArrayList<>();
        //初始化女生信息
        for (int i = 0; i < 10; i++) {
            girls.add(new Girl());
        }
        ;
        Teacher teacher = new Teacher();
        //老師發(fā)布命令
        teacher.command(new GroupLeader(girls));
    }
}

對程序進行了簡單的修改,把Teacher的List<Girl>的初始化移動到了場景類中,同時在GroupLeader中增加對Girl的注入,避開了Teacher對陌生類Girl的訪問,降低了系統(tǒng)間耦合,提高了系統(tǒng)的健壯性。

(二)、朋友間也是有距離的

人和人之間是有距離的,太遠關(guān)系逐漸疏遠,最終形同陌路;太近就相互刺傷。迪米特法則就是對這個距離進行描述,即使是朋友類之間也不能無話不說,無所不知。

我們在安裝軟件的時候,經(jīng)常會有一個導(dǎo)向動作,第一步是確認(rèn)是否安裝,第二步確認(rèn)Lisence,再然后選擇安裝目錄...這是一個典型的順序執(zhí)行動作,具體到程序中就是:調(diào)用一個或多個類,先執(zhí)行第一個方法,然后是第二個方法,根據(jù)返回結(jié)果再來看是否可以調(diào)用第三個方法,或者第四個方法,等等。其類圖大體如下:

實現(xiàn)過程如下:

public class Wizard {
    private Random random = new Random(System.currentTimeMillis());
    /**
     * 第一步
     *
     * @return
     */
    public int first() {
        System.out.println("執(zhí)行第一個方法");
        return random.nextInt(100);
    }
    /**
     * 第二步
     *
     * @return
     */
    public int second() {
        System.out.println("執(zhí)行第二個方法");
        return random.nextInt(100);
    }
    /**
     * 第三步
     *
     * @return
     */
    public int third() {
        System.out.println("執(zhí)行第三個方法");
        return random.nextInt(100);
    }
}

在Wizard類中分別定義了三個步驟方法,每個步驟中都有相關(guān)的業(yè)務(wù)邏輯完成指定的任務(wù),我們使用一個隨機函數(shù)來代替業(yè)務(wù)執(zhí)行的返回值。

InstallSoftware類的代碼如下:

public class InstallSoftware {
    public void install(Wizard wizard) {
        int first = wizard.first();
        //根據(jù)first的返回結(jié)果,看是否需要執(zhí)行second
        if (first > 50) {
            int second = wizard.second();
            if (second > 50) {
                int third = wizard.third();
                if (third > 50) {
                    wizard.first();
                }
            }
        }
    }
}

根據(jù)每個方法執(zhí)行的結(jié)果決定是否繼續(xù)執(zhí)行下一個方法,模擬人工的選擇操作。場景類如下:

public class Client {
    public static void main(String[] args) {
        InstallSoftware installSoftware = new InstallSoftware();
        installSoftware.install(new Wizard());
    }
}

以上程序很簡單,運行結(jié)果和隨機數(shù)有關(guān),每次執(zhí)行的結(jié)果都不相同,需要讀者自己運行并查看結(jié)果。程序雖然簡單,但隱藏的問題可不簡單,思考一下程序有什么問題?

Wizard類把太多的方法暴露給InstallSoftware類,兩者的朋友關(guān)系太親密了,耦合關(guān)系變得異常牢固。如果要將Wizard類中的first方法返回值的類型由int修改為boolean,就需要修改InstallSoftware類,從而把修改變更的風(fēng)險擴散開了。因此,這種耦合是不合適的,我們需要對設(shè)計進行重構(gòu),重構(gòu)后的類圖如下:

在Wizard類中增加一個installWizard方法,對安裝過程進行封裝,同時把所有的三個public方法修改為private方法,如下:

public class Wizard {
    private Random random = new Random(System.currentTimeMillis());
    /**
     * 第一步
     *
     * @return
     */
    private int first() {
        System.out.println("執(zhí)行第一個方法");
        return random.nextInt(100);
    }
    /**
     * 第二步
     *
     * @return
     */
    private int second() {
        System.out.println("執(zhí)行第二個方法");
        return random.nextInt(100);
    }
    /**
     * 第三步
     *
     * @return
     */
    private int third() {
        System.out.println("執(zhí)行第三個方法");
        return random.nextInt(100);
    }
    public void installWizard() {
        int first = this.first();
        //根據(jù)first的返回結(jié)果,看是否需要執(zhí)行second
        if (first > 50) {
            int second = this.second();
            if (second > 50) {
                int third = this.third();
                if (third > 50) {
                    this.first();
                }
            }
        }
    }
}

講啊三個步驟的訪問權(quán)限修改為private,同時把InstallSoftware中的方法installWizard()移動到了Wizard類中。通過這樣的重構(gòu)后,Wizard類就只對外公布了一個public方法,即使要修改first方法的返回值,影響的也僅僅是Wizard本身,其他類不受影響,這顯示了類的高內(nèi)聚特性。

修改后的InstallSoftware代碼如下:

public class InstallSoftware {
    public void install(Wizard wizard) {
        wizard.installWizard();
    }
}

場景類沒有任何改變,通過進行重構(gòu),類間的耦合關(guān)系變?nèi)趿耍Y(jié)構(gòu)也清晰了,變更引起的風(fēng)險也變小了。

一個類公開的public屬性或者方法越多,修改時涉及的面就越大,變更引起的風(fēng)險擴散也就越大。因此,為了保持朋友間的距離,在設(shè)計時需要反復(fù)衡量:是否還可以再減少public屬性和方法,是否可以修改為private、package-private、protected等訪問權(quán)限,是否可以加上final關(guān)鍵字等。

(三)、是自己的就是自己的

在實際應(yīng)用中經(jīng)常會出現(xiàn)這樣一個方法:放在本類中也可以,放在其他類也沒有錯,那怎么去衡量呢?可以檢查這樣一個原則:如果一個方法放在本類中,既不增加類間關(guān)系,也對本類不產(chǎn)生負面影響,那就放置在本類中。

三、總結(jié)

迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以后,類的復(fù)用率才可以提高。其要求的結(jié)果就是產(chǎn)生了大量的中轉(zhuǎn)或跳轉(zhuǎn)類,導(dǎo)致系統(tǒng)的復(fù)雜性提高,同時也為維護帶來了難度。讀者在采用迪米特法則的時候需要反復(fù)權(quán)衡,既做到讓結(jié)構(gòu)清晰,又做到高內(nèi)聚低耦合。

到此這篇關(guān)于Java面向?qū)ο笤O(shè)計原則之迪米特法則介紹的文章就介紹到這了,更多相關(guān)Java迪米特法則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis之動態(tài)SQL使用小結(jié)(全網(wǎng)最新)

    Mybatis之動態(tài)SQL使用小結(jié)(全網(wǎng)最新)

    MyBatis令人喜歡的一大特性就是動態(tài)SQL,?在使用JDBC的過程中,?根據(jù)條件進行SQL的拼接是很麻煩且很容易出錯的,MyBatis通過OGNL來進行動態(tài)SQL的使用解決了這個麻煩,對Mybatis動態(tài)SQL相關(guān)知識感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • java查詢近七日數(shù)據(jù)功能的實現(xiàn)

    java查詢近七日數(shù)據(jù)功能的實現(xiàn)

    這篇文章主要介紹了java查詢近七日數(shù)據(jù)功能的實現(xiàn),文章內(nèi)容詳細,簡單易懂,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2023-01-01
  • Java Swing null絕對布局的實現(xiàn)示例

    Java Swing null絕對布局的實現(xiàn)示例

    這篇文章主要介紹了Java Swing null絕對布局的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 原因分析IDEA導(dǎo)入Spring-kafka項目Gradle編譯失敗

    原因分析IDEA導(dǎo)入Spring-kafka項目Gradle編譯失敗

    這篇文章主要為大家介紹分析了IDEA導(dǎo)入Spring-kafka項目Gradle中編譯失敗原因及解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • Mybatis游標(biāo)查詢大量數(shù)據(jù)方式

    Mybatis游標(biāo)查詢大量數(shù)據(jù)方式

    這篇文章主要介紹了Mybatis游標(biāo)查詢大量數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 詳解java開發(fā)webservice的幾種方式

    詳解java開發(fā)webservice的幾種方式

    webservice的應(yīng)用已經(jīng)越來越廣泛了,下面介紹幾種在Java體系中開發(fā)webservice的方式,有興趣的可以了解一下。
    2016-11-11
  • 淺談JavaWeb中的web.xml配置部署描述符文件

    淺談JavaWeb中的web.xml配置部署描述符文件

    下面小編就為大家?guī)硪黄獪\談JavaWeb中的web.xml配置部署描述符文件。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • JAVA中JVM的重排序詳細介紹

    JAVA中JVM的重排序詳細介紹

    重排序通常是編譯器或運行時環(huán)境為了優(yōu)化程序性能而采取的對指令進行重新排序執(zhí)行的一種手段。重排序分為兩類:編譯期重排序和運行期重排序,分別對應(yīng)編譯時和運行時環(huán)境
    2014-05-05
  • springcloud 中 zuul 修改請求參數(shù)信息的方法

    springcloud 中 zuul 修改請求參數(shù)信息的方法

    這篇文章主要介紹了springcloud 中 zuul 修改請求參數(shù)信息的方法,需要的朋友可以參考下
    2018-02-02
  • Java實現(xiàn)word文檔轉(zhuǎn)成圖片的示例詳解

    Java實現(xiàn)word文檔轉(zhuǎn)成圖片的示例詳解

    本文主要為大家詳細介紹了如何在Java項目中引用aspose-words和poi-tljar包實現(xiàn)word文檔轉(zhuǎn)成圖片,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-10-10

最新評論