設計模式系列(六)七大設計原則-----迪米特法則與合成複用原則
阿新 • • 發佈:2020-10-12
迪米特法則
- 一個物件應該對其他物件保持最少的瞭解
- 類與類的關係越密切,耦合度越大
- 迪米特法則又稱為 最少知道原則,即一個類 對自己依賴的類知道的越少越好。也就是說,對於被依賴的類不管多麼複雜,都儘量將邏輯封裝在類的內部。對外除了提供的 public 方法,不對外洩露任何資訊
- 迪米特法則還有個更簡單的定義:只與 直接的朋友通訊
- 直接的朋友:每個物件都會與其他物件有 耦合關係,只要兩個物件之間有耦合關係,我們就說這兩個物件之間是朋友關係。耦合的方式很多,依賴,關聯,組合,聚合等。其中,我們稱出現 成員變數,方法引數,方法返回值 中的類為直接朋友,而出現在 區域性變數中的類不是直接的朋友。也就是說,陌生的類最好不要以區域性變數的形式出現類的內部。
例項
- 有一個學校,下屬有各個學院和總部,現要求打印出學校總部員工ID 和學院員工的id
- 程式碼實現
public class Demeter1 { public static void main(String[] args) { //建立了一個SchoolManager 物件 SchoolManager schoolManager = new SchoolManager(); //輸出學院的員工id 和學校總部的員工資訊 schoolManager.printAllEmployee(new CollegeManager()); } } //學校總部員工類 class Employee { private String id; public void setId(String id) { this.id = id; } public String getId() { return id; } } //學院的員工類 class CollegeEmployee { private String id; public void setId(String id) { this.id = id; } public String getId() { return id; } } //管理學院員工的管理類 class CollegeManager { //返回學院的所有員工 public List<CollegeEmployee> getAllEmployee() { List<CollegeEmployee> list = new ArrayList<CollegeEmployee>(); for (int i = 0; i < 10; i++) { //這裡我們增加了10 個員工到list CollegeEmployee emp = new CollegeEmployee(); emp.setId("學院員工id= " + i); list.add(emp); } return list; } } //學校管理類 //分析SchoolManager 類的直接朋友類有哪些Employee、CollegeManager //CollegeEmployee 不是直接朋友而是一個陌生類,這樣違背了迪米特法則 class SchoolManager { //返回學校總部的員工 public List<Employee> getAllEmployee() { List<Employee> list = new ArrayList<Employee>(); for (int i = 0; i < 5; i++) { //這裡我們增加了5 個員工到list Employee emp = new Employee(); emp.setId("學校總部員工id= " + i); list.add(emp); } return list; } //該方法完成輸出學校總部和學院員工資訊(id) void printAllEmployee(CollegeManager sub) { //分析問題 //1. 這裡的CollegeEmployee 不是SchoolManager 的直接朋友 //2. CollegeEmployee 是以區域性變數方式出現在SchoolManager //3. 違反了迪米特法則 //獲取到學院員工 List<CollegeEmployee> list1 = sub.getAllEmployee(); System.out.println("------------學院員工------------"); for (CollegeEmployee e : list1) { System.out.println(e.getId()); } //獲取到學校總部員工 List<Employee> list2 = this.getAllEmployee(); System.out.println("------------學校總部員工------------"); for (Employee e : list2) { System.out.println(e.getId()); } } }
改進
- 說明
- 前面設計的問題在於 SchoolManager 中,CollegeEmployee 類並不是SchoolManager 類的直接朋友(分析)
- 按照迪米特法則,應該避免類中出現這樣非直接朋友關係的耦合
- 程式碼
//客戶端 public class Demeter1 { public static void main(String[] args) { System.out.println("~~~使用迪米特法則的改進~~~"); //建立了一個SchoolManager 物件 SchoolManager schoolManager = new SchoolManager(); //輸出學院的員工id 和學校總部的員工資訊 schoolManager.printAllEmployee(new CollegeManager()); } } //學校總部員工類 class Employee { private String id; public void setId(String id) { this.id = id; } public String getId() { return id; } } //學院的員工類 class CollegeEmployee { private String id; public void setId(String id) { this.id = id; } public String getId() { return id; } } //管理學院員工的管理類 class CollegeManager { //返回學院的所有員工 public List<CollegeEmployee> getAllEmployee() { List<CollegeEmployee> list = new ArrayList<CollegeEmployee>(); for (int i = 0; i < 10; i++) { //這裡我們增加了10 個員工到list CollegeEmployee emp = new CollegeEmployee(); emp.setId("學院員工id= " + i); list.add(emp); } return list; } //輸出學院員工的資訊 public void printEmployee() { //獲取到學院員工 List<CollegeEmployee> list1 = getAllEmployee(); System.out.println("------------學院員工------------"); for (CollegeEmployee e : list1) { System.out.println(e.getId()); } } } //學校管理類 //分析SchoolManager 類的直接朋友類有哪些Employee、CollegeManager //CollegeEmployee 不是直接朋友而是一個陌生類,這樣違背了迪米特法則 class SchoolManager { //返回學校總部的員工 public List<Employee> getAllEmployee() { List<Employee> list = new ArrayList<Employee>(); for (int i = 0; i < 5; i++) { //這裡我們增加了5 個員工到list Employee emp = new Employee(); emp.setId("學校總部員工id= " + i); list.add(emp); } return list; } //該方法完成輸出學校總部和學院員工資訊(id) void printAllEmployee(CollegeManager sub) { //分析問題 //1. 將輸出學院的員工方法,封裝到CollegeManager sub.printEmployee(); //獲取到學校總部員工 List<Employee> list2 = this.getAllEmployee(); System.out.println("------------學校總部員工------------"); for (Employee e : list2) { System.out.println(e.getId()); } } }
- 注意事項
- 迪米特法則的核心是降低類之間的耦合
- 但是注意:由於每個類都減少了不必要的依賴,因此迪米特法則只是要求降低類間(物件間)耦合關係, 並不是
要求完全沒有依賴關係
合成複用原則
合成複用原則設計的核心思想:
- 找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的程式碼混在一起。
- 針對介面程式設計,而不是針對實現程式設計。
- 為了互動物件之間的 鬆耦合設計而努力