迪米特法則

1. 概念

  • 迪米特法則(Demeter Principle)又叫最少知道原則,即一個類對自己依賴的類知道的越少越好。
  • 迪米特法則還有個更簡單的定義:只與直接的朋友通信
    • 朋友:有耦合(依賴,關(guān)聯(lián),組合,聚合)關(guān)系的對象
    • 直接的朋友:成員變量,方法參數(shù),方法返回值中的類

2. 優(yōu)點

  • 降低耦合性,提高模塊功能的獨立性
  • 非常實用,能直接用于開發(fā)環(huán)境

3. 代碼示例

示例1(違背迪米特法則的案例)

package com.bz.design.principle.demeter;

import java.util.ArrayList;
import java.util.List;

// 客戶端
public class Demeter001 {

    public static void main(String[] args) {
        //創(chuàng)建了一個SchoolManager對象
        SchoolManager schoolManager = new SchoolManager();
        //輸出學(xué)院的員工id和學(xué)校總部的員工信息
        schoolManager.printAllEmployee(new CollegeManager());
    }
}

// 總部員工
class Employee {
    private String id;

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }
}

// 學(xué)院員工
class CollegeEmployee {
    private String id;

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }
}

// 管理學(xué)院員工的類
class CollegeManager {
    // 返回學(xué)院的所有員工
    public List<CollegeEmployee> getAllEmployee() {
        List<CollegeEmployee> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            CollegeEmployee emp = new CollegeEmployee();
            emp.setId("學(xué)院員工id=" + i);
            list.add(emp);
        }
        return list;
    }
}

// 學(xué)校管理類
// 分析 SchoolManager 類的直接朋友 Employee、CollegeManager
// CollegeEmployee 不是直接朋友,違反了迪米特法則
class SchoolManager {
    // 返回學(xué)??偛康膯T工
    public List<Employee> getAllEmployee() {
        List<Employee> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Employee emp = new Employee();
            emp.setId("學(xué)??偛繂T工id=" + i);
            list.add(emp);
        }
        return list;
    }

    // 該方法完成輸出學(xué)校總部和學(xué)院員工信息的方法
    void printAllEmployee(CollegeManager sub) {
        // 分析問題
        // 1.這里的CollegeEmployee 不是SchoolManager的直接朋友
        // 2.CollegeEmployee 是以局部變量方式出現(xiàn)在SchoolManager
        // 3.違反了迪米特法則
        List<CollegeEmployee> list1 = sub.getAllEmployee();
        System.out.println("----------學(xué)院員工----------");
        for (CollegeEmployee e : list1) {
            System.out.println(e.getId());
        }
        List<Employee> list2 = this.getAllEmployee();
        System.out.println("------------學(xué)??偛繂T工------------");
        for (Employee e : list2) {
            System.out.println(e.getId());
        }
    }
}

示例2

  • 應(yīng)用實例改進
    • 前面設(shè)計的問題在于SchoolManager中,CollegeEmployee類并不不是SchoolManager類的直接朋友(分析)
    • 按照迪米特法則,應(yīng)該避免類中出現(xiàn)這樣非直接朋友關(guān)系的耦合
    • 對代碼按照迪米特法則進行改進
package com.bz.design.principle.demeter.improve;

import java.util.ArrayList;
import java.util.List;

/**
 * 應(yīng)用實例改進
 * 1)前面設(shè)計的問題在于SchoolManager中,CollegeEmployee類并不不是SchoolManager類的直接朋友(分析)
 * 2)按照迪米特法則,應(yīng)該避免類中出現(xiàn)這樣非直接朋友關(guān)系的耦合
 * 3)對代碼按照迪米特法則進行改進
 */
public class DemeterImprove {

    public static void main(String[] args) {
        System.out.println("---使用迪米特法則改進---");
        //創(chuàng)建了一個SchoolManager對象
        SchoolManager schoolManager = new SchoolManager();
        //輸出學(xué)院的員工id和學(xué)校總部的員工信息
        schoolManager.printAllEmployee(new CollegeManager());
    }
}

// 總部員工
class Employee {
    private String id;

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }
}

// 學(xué)院員工
class CollegeEmployee {
    private String id;

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }
}

// 管理學(xué)院員工的類
class CollegeManager {
    // 返回學(xué)院的所有員工
    public List<CollegeEmployee> getAllEmployee() {
        List<CollegeEmployee> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            CollegeEmployee emp = new CollegeEmployee();
            emp.setId("學(xué)院員工id=" + i);
            list.add(emp);
        }
        return list;
    }

    // 改進點
    // 輸出學(xué)院員工的信息
    public void printEmployee() {
        // 獲取到學(xué)院員工
        List<CollegeEmployee> list1 = this.getAllEmployee();
        System.out.println("----------學(xué)院員工----------");
        for (CollegeEmployee e : list1) {
            System.out.println(e.getId());
        }
    }
}

// 學(xué)校管理類
class SchoolManager {
    // 返回學(xué)??偛康膯T工
    public List<Employee> getAllEmployee() {
        List<Employee> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Employee emp = new Employee();
            emp.setId("學(xué)??偛繂T工id=" + i);
            list.add(emp);
        }
        return list;
    }

    // 該方法完成輸出學(xué)校總部和學(xué)院員工信息的方法
    void printAllEmployee(CollegeManager sub) {
        // 分析問題
        // 將輸出學(xué)院的員工方法,封裝到CollegeManager
        sub.printEmployee();
        List<Employee> list2 = this.getAllEmployee();
        System.out.println("------------學(xué)校總部員工------------");
        for (Employee e : list2) {
            System.out.println(e.getId());
        }
    }
}

4. 應(yīng)用注意事項

  • 不要干
    • objectA.getObjectB().doSomething();
    • objectA.getObjectB().getObjectC().doSomething();
  • 遵循迪米特法則的設(shè)計模式
    • 門面模式Facade
    • 中介模式Mediator
  • 注意事項
    • 有可能存在大量中介類(濫用會出現(xiàn))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容