迪米特法則
- 一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解
- 類(lèi)與類(lèi)的關(guān)系越密切,耦合度越大
- 迪米特法則又稱(chēng)為 最少知道原則,即一個(gè)類(lèi) 對(duì)自己依賴(lài)的類(lèi)知道的越少越好。也就是說(shuō),對(duì)于被依賴(lài)的類(lèi)不管多么復(fù)雜,都盡量將邏輯封裝在類(lèi)的內(nèi)部。對(duì)外除了提供的 public 方法,不對(duì)外泄露任何信息
- 迪米特法則還有個(gè)更簡(jiǎn)單的定義:只與 直接的朋友通信
- 直接的朋友:每個(gè)對(duì)象都會(huì)與其他對(duì)象有 耦合關(guān)系,只要兩個(gè)對(duì)象之間有耦合關(guān)系,我們就說(shuō)這兩個(gè)對(duì)象之間是朋友關(guān)系。耦合的方式很多,依賴(lài),關(guān)聯(lián),組合,聚合等。其中,我們稱(chēng)出現(xiàn) 成員變量,方法參數(shù),方法返回值 中的類(lèi)為直接朋友,而出現(xiàn)在 局部變量中的類(lèi)不是直接的朋友。也就是說(shuō),陌生的類(lèi)最好不要以局部變量的形式出現(xiàn)類(lèi)的內(nèi)部。
實(shí)例
- 有一個(gè)學(xué)校,下屬有各個(gè)學(xué)院和總部,現(xiàn)要求打印出學(xué)校總部員工ID 和學(xué)院?jiǎn)T工的id
- 代碼實(shí)現(xiàn)
public class Demeter1 {
public static void main(String[] args) {
//創(chuàng)建了一個(gè)SchoolManager 對(duì)象
SchoolManager schoolManager = new SchoolManager();
//輸出學(xué)院的員工id 和學(xué)??偛康膯T工信息
schoolManager.printAllEmployee(new CollegeManager());
}
}
//學(xué)校總部員工類(lèi)
class Employee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//學(xué)院的員工類(lèi)
class CollegeEmployee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//管理學(xué)院?jiǎn)T工的管理類(lèi)
class CollegeManager {
//返回學(xué)院的所有員工
public List<CollegeEmployee> getAllEmployee() {
List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
for (int i = 0; i < 10; i++) { //這里我們?cè)黾恿?0 個(gè)員工到list
CollegeEmployee emp = new CollegeEmployee();
emp.setId("學(xué)院?jiǎn)T工id= " + i);
list.add(emp);
}
return list;
}
}
//學(xué)校管理類(lèi)
//分析SchoolManager 類(lèi)的直接朋友類(lèi)有哪些Employee、CollegeManager
//CollegeEmployee 不是直接朋友而是一個(gè)陌生類(lèi),這樣違背了迪米特法則
class SchoolManager {
//返回學(xué)校總部的員工
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<Employee>();
for (int i = 0; i < 5; i++) { //這里我們?cè)黾恿? 個(gè)員工到list
Employee emp = new Employee();
emp.setId("學(xué)校總部員工id= " + i);
list.add(emp);
}
return list;
}
//該方法完成輸出學(xué)??偛亢蛯W(xué)院?jiǎn)T工信息(id)
void printAllEmployee(CollegeManager sub) {
//分析問(wèn)題
//1. 這里的CollegeEmployee 不是SchoolManager 的直接朋友
//2. CollegeEmployee 是以局部變量方式出現(xiàn)在SchoolManager
//3. 違反了迪米特法則
//獲取到學(xué)院?jiǎn)T工
List<CollegeEmployee> list1 = sub.getAllEmployee();
System.out.println("------------學(xué)院?jiǎn)T工------------");
for (CollegeEmployee e : list1) {
System.out.println(e.getId());
}
//獲取到學(xué)??偛繂T工
List<Employee> list2 = this.getAllEmployee();
System.out.println("------------學(xué)??偛繂T工------------");
for (Employee e : list2) {
System.out.println(e.getId());
}
}
}
改進(jìn)
- 說(shuō)明
- 前面設(shè)計(jì)的問(wèn)題在于 SchoolManager 中,CollegeEmployee 類(lèi)并不是SchoolManager 類(lèi)的直接朋友(分析)
- 按照迪米特法則,應(yīng)該避免類(lèi)中出現(xiàn)這樣非直接朋友關(guān)系的耦合
- 代碼
//客戶(hù)端
public class Demeter1 {
public static void main(String[] args) {
System.out.println("~~~使用迪米特法則的改進(jìn)~~~");
//創(chuàng)建了一個(gè)SchoolManager 對(duì)象
SchoolManager schoolManager = new SchoolManager();
//輸出學(xué)院的員工id 和學(xué)??偛康膯T工信息
schoolManager.printAllEmployee(new CollegeManager());
}
}
//學(xué)校總部員工類(lèi)
class Employee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//學(xué)院的員工類(lèi)
class CollegeEmployee {
private String id;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
//管理學(xué)院?jiǎn)T工的管理類(lèi)
class CollegeManager {
//返回學(xué)院的所有員工
public List<CollegeEmployee> getAllEmployee() {
List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
for (int i = 0; i < 10; i++) { //這里我們?cè)黾恿?0 個(gè)員工到list
CollegeEmployee emp = new CollegeEmployee();
emp.setId("學(xué)院?jiǎn)T工id= " + i);
list.add(emp);
}
return list;
}
//輸出學(xué)院?jiǎn)T工的信息
public void printEmployee() {
//獲取到學(xué)院?jiǎn)T工
List<CollegeEmployee> list1 = getAllEmployee();
System.out.println("------------學(xué)院?jiǎn)T工------------");
for (CollegeEmployee e : list1) {
System.out.println(e.getId());
}
}
}
//學(xué)校管理類(lèi)
//分析SchoolManager 類(lèi)的直接朋友類(lèi)有哪些Employee、CollegeManager
//CollegeEmployee 不是直接朋友而是一個(gè)陌生類(lèi),這樣違背了迪米特法則
class SchoolManager {
//返回學(xué)??偛康膯T工
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<Employee>();
for (int i = 0; i < 5; i++) { //這里我們?cè)黾恿? 個(gè)員工到list
Employee emp = new Employee();
emp.setId("學(xué)??偛繂T工id= " + i);
list.add(emp);
}
return list;
}
//該方法完成輸出學(xué)校總部和學(xué)院?jiǎn)T工信息(id)
void printAllEmployee(CollegeManager sub) {
//分析問(wèn)題
//1. 將輸出學(xué)院的員工方法,封裝到CollegeManager
sub.printEmployee();
//獲取到學(xué)??偛繂T工
List<Employee> list2 = this.getAllEmployee();
System.out.println("------------學(xué)校總部員工------------");
for (Employee e : list2) {
System.out.println(e.getId());
}
}
}
- 注意事項(xiàng)
- 迪米特法則的核心是降低類(lèi)之間的耦合
- 但是注意:由于每個(gè)類(lèi)都減少了不必要的依賴(lài),因此迪米特法則只是要求降低類(lèi)間(對(duì)象間)耦合關(guān)系, 并不是
要求完全沒(méi)有依賴(lài)關(guān)系
合成復(fù)用原則
在這里插入圖片描述
合成復(fù)用原則設(shè)計(jì)的核心思想:
- 找出應(yīng)用中可能需要變化之處,把它們獨(dú)立出來(lái),不要和那些不需要變化的代碼混在一起。
- 針對(duì)接口編程,而不是針對(duì)實(shí)現(xiàn)編程。
- 為了交互對(duì)象之間的 松耦合設(shè)計(jì)而努力