1. 概念
- 迪米特法則(Demeter Principle)又叫最少知道原則供搀,即一個(gè)類(lèi)對(duì)自己依賴(lài)的類(lèi)知道的越少越好屯烦。
- 迪米特法則還有個(gè)更簡(jiǎn)單的定義:只與直接的朋友通信
- 朋友:有耦合(依賴(lài),關(guān)聯(lián),組合,聚合)關(guān)系的對(duì)象
- 直接的朋友:成員變量成福,方法參數(shù),方法返回值中的類(lèi)
2. 優(yōu)點(diǎn)
- 降低耦合性,提高模塊功能的獨(dú)立性
- 非常實(shí)用,能直接用于開(kāi)發(fā)環(huán)境
3. 代碼示例
示例1(違背迪米特法則的案例)
package com.bz.design.principle.demeter;
import java.util.ArrayList;
import java.util.List;
// 客戶(hù)端
public class Demeter001 {
public static void main(String[] args) {
//創(chuàng)建了一個(gè)SchoolManager對(duì)象
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é)院?jiǎn)T工
class CollegeEmployee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return this.id;
}
}
// 管理學(xué)院?jiǎn)T工的類(lèi)
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é)院?jiǎn)T工id=" + i);
list.add(emp);
}
return list;
}
}
// 學(xué)校管理類(lèi)
// 分析 SchoolManager 類(lèi)的直接朋友 Employee吹榴、CollegeManager
// CollegeEmployee 不是直接朋友胧洒,違反了迪米特法則
class SchoolManager {
// 返回學(xué)形废牛總部的員工
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("學(xué)校總部員工id=" + i);
list.add(emp);
}
return list;
}
// 該方法完成輸出學(xué)形缆總部和學(xué)院?jiǎn)T工信息的方法
void printAllEmployee(CollegeManager sub) {
// 分析問(wèn)題
// 1.這里的CollegeEmployee 不是SchoolManager的直接朋友
// 2.CollegeEmployee 是以局部變量方式出現(xiàn)在SchoolManager
// 3.違反了迪米特法則
List<CollegeEmployee> list1 = sub.getAllEmployee();
System.out.println("----------學(xué)院?jiǎn)T工----------");
for (CollegeEmployee e : list1) {
System.out.println(e.getId());
}
List<Employee> list2 = this.getAllEmployee();
System.out.println("------------學(xué)蟹票總部員工------------");
for (Employee e : list2) {
System.out.println(e.getId());
}
}
}
示例2
- 應(yīng)用實(shí)例改進(jìn)
- 前面設(shè)計(jì)的問(wèn)題在于SchoolManager中,CollegeEmployee類(lèi)并不不是SchoolManager類(lèi)的直接朋友(分析)
- 按照迪米特法則列赎,應(yīng)該避免類(lèi)中出現(xiàn)這樣非直接朋友關(guān)系的耦合
- 對(duì)代碼按照迪米特法則進(jìn)行改進(jìn)
package com.bz.design.principle.demeter.improve;
import java.util.ArrayList;
import java.util.List;
/**
* 應(yīng)用實(shí)例改進(jìn)
* 1)前面設(shè)計(jì)的問(wèn)題在于SchoolManager中,CollegeEmployee類(lèi)并不不是SchoolManager類(lèi)的直接朋友(分析)
* 2)按照迪米特法則,應(yīng)該避免類(lèi)中出現(xiàn)這樣非直接朋友關(guān)系的耦合
* 3)對(duì)代碼按照迪米特法則進(jìn)行改進(jìn)
*/
public class DemeterImprove {
public static void main(String[] args) {
System.out.println("---使用迪米特法則改進(jìn)---");
//創(chuàng)建了一個(gè)SchoolManager對(duì)象
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é)院?jiǎn)T工
class CollegeEmployee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return this.id;
}
}
// 管理學(xué)院?jiǎn)T工的類(lèi)
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é)院?jiǎn)T工id=" + i);
list.add(emp);
}
return list;
}
// 改進(jìn)點(diǎn)
// 輸出學(xué)院?jiǎn)T工的信息
public void printEmployee() {
// 獲取到學(xué)院?jiǎn)T工
List<CollegeEmployee> list1 = this.getAllEmployee();
System.out.println("----------學(xué)院?jiǎn)T工----------");
for (CollegeEmployee e : list1) {
System.out.println(e.getId());
}
}
}
// 學(xué)校管理類(lèi)
class SchoolManager {
// 返回學(xué)校總部的員工
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("學(xué)校總部員工id=" + i);
list.add(emp);
}
return list;
}
// 該方法完成輸出學(xué)斜罚總部和學(xué)院?jiǎn)T工信息的方法
void printAllEmployee(CollegeManager sub) {
// 分析問(wèn)題
// 將輸出學(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)用注意事項(xiàng)
-
不要干
- objectA.getObjectB().doSomething();
- objectA.getObjectB().getObjectC().doSomething();
-
遵循迪米特法則的設(shè)計(jì)模式
- 門(mén)面模式Facade
- 中介模式Mediator
- 注意事項(xiàng)
- 有可能存在大量中介類(lèi)(濫用會(huì)出現(xiàn))