設計原則系列文章 必知必會的設計原則——介面隔離原則 必知必會的設計原則——單一職責原則 必知必會的設計原則——開放封閉原則 必知必會的設計原則——依賴倒置原則 必知必會的設計原則——里氏替換原則 概述 迪米特法則(Law of Demeter )又叫做最少知識原則,即一個對象應該對另一個對象有最少 ...
設計原則系列文章
概述
迪米特法則(Law of Demeter )又叫做最少知識原則,即一個對象應該對另一個對象有最少的瞭解。
迪米特法則的目的在於降低類之間的耦合。由於每個類儘量減少對其他類的依賴,因此,很容易使得系統的功能模塊功能獨立,相互之間不存在(或很少有)依賴關係。
迪米特原則實際上就是一個類在創建方法和屬性時要遵守的法則;
迪米特原則核心指導思想為只和直接朋友通信(成員對象、方法參數、方法返回值;值出現在局部變數的類 ,不是直接朋友)。
案例需求1
實現人關機電腦(人關機電腦一般最起碼分為三個步驟,第一步先保存當前的任務,第二步關閉屏幕,第三步關機電源)。
未使用迪米特原則的代碼
public class Computer { public void SaveTask() { Console.WriteLine("保存當前電腦任務"); } public void CloseScreen() { Console.WriteLine("關閉屏幕"); } public void ShutDown() { Console.WriteLine("關閉電源"); } } public class Person { public void CloseComputer(Computer computer) {computer.SaveTask(); computer.CloseScreen(); computer.ShutDown(); } }
上面person類中的CloseComputer方法中邏輯不符合迪米特原則,如果關機需要三十步,computer需要提供30個方法,每個方法之間都有相應的絕對順序。
使用迪米特原則的代碼
public class Computer { public void SaveTask() { Console.WriteLine("保存當前電腦任務"); } public void CloseScreen() { Console.WriteLine("關閉屏幕"); } public void ShutDown() { Console.WriteLine("關閉電源"); } public void CloseComputer() { this.SaveTask(); this.CloseScreen(); this.ShutDown(); } } //person類中closecomputer方法中的參數computer為直接朋友,符合迪米特原則 public class Person { public void CloseComputer(Computer computer) { computer.CloseComputer(); } }
上面person類中的CloseComputer方法只負責調用Computer中的CloseComputer方法,如果關機電腦這個需求有其他的變化,computer類裡面添加方法或發生邏輯變化,person類始終不會發生改變。
關於迪米特原則很多人聽到這個詞,估計有點陌生,真實編程中可能這樣用過,但不知道其名字,所以我們再來看一個案例需求,加深鞏固理解。
案例需求2
分別列印總公司和分公司員工的編號;
未使用迪米特原則的代碼
public class HeadOfficeEmployee { public int Id { get; set; } } /// <summary> /// 總公司管理者 /// </summary> public class HeadOfficeManager { /// <summary> /// 獲取員工數 /// </summary> /// <returns></returns> public List<HeadOfficeEmployee> GetEmployees() { List<HeadOfficeEmployee> headOffices = new List<HeadOfficeEmployee>(); for (int i = 0; i < 10; i++) { HeadOfficeEmployee headOfficeEmployee = new HeadOfficeEmployee(); headOfficeEmployee.Id = i; headOffices.Add(headOfficeEmployee); } return headOffices; } /// <summary> /// 列印總公司員工id /// </summary> public void Print(BranchOfficeManager branchOfficeManager) { var datas= GetEmployees(); Console.WriteLine("總公司員工Id分別是:" ); foreach (var item in datas) { Console.WriteLine(+item.Id); } //branchOfficeEmployes這個集合對象,是通過局部變數的形式出現在類中的,所以不是我們的直接朋友,故不符合迪米特原則。 var branchOfficeEmployes= branchOfficeManager.GetEmployees(); Console.WriteLine("分公司員工Id分別是:"); foreach (var item in branchOfficeEmployes) { Console.WriteLine(+item.Id); } } }
//C# 控制台調用 BranchOfficeManager branchOfficeManager = new BranchOfficeManager(); new HeadOfficeManager().Print(branchOfficeManager);
以上HeadOfficeManager類中Print方法傳遞的參數branchOfficeManager是直接朋友,GetEmployee()中返回的集合對象也是直接朋友符合迪米特原則,但branchOfficeManager.GetEmployees()獲取的集合branchOfficeEmployes是通過局部變數的形式出現在類中的,所以不符合迪米特原則。
使用迪米特原則改造後的代碼
/// <summary> /// 總公司員工 /// </summary> public class HeadOfficeEmployee { public int Id { get; set; } } /// <summary> /// 總公司管理者 /// </summary> public class HeadOfficeManager { /// <summary> /// 獲取員工數 /// </summary> /// <returns></returns> public List<HeadOfficeEmployee> GetEmployees() { List<HeadOfficeEmployee> headOffices = new List<HeadOfficeEmployee>(); for (int i = 0; i < 10; i++) { HeadOfficeEmployee headOfficeEmployee = new HeadOfficeEmployee(); headOfficeEmployee.Id = i; headOffices.Add(headOfficeEmployee); } return headOffices; } /// <summary> /// 列印總公司員工id /// </summary> public void Print() { var datas= GetEmployees(); Console.WriteLine("總公司員工Id分別是:" ); foreach (var item in datas) { Console.WriteLine(+item.Id); } }
}
/// <summary> /// 分公司員工類 /// </summary> public class BranchOfficeEmployee { public int Id { get; set; } } /// <summary> /// 分公司員工管理者 /// </summary> public class BranchOfficeManager { public List<BranchOfficeEmployee> GetEmployees() { List<BranchOfficeEmployee> headOffices = new List<BranchOfficeEmployee>(); for (int i = 0; i < 10; i++) { BranchOfficeEmployee headOfficeEmployee = new BranchOfficeEmployee(); headOfficeEmployee.Id = i; headOffices.Add(headOfficeEmployee); } return headOffices; } /// <summary> /// 列印分公司每個員工Id /// </summary> public void Print() { var datas= GetEmployees(); Console.WriteLine("分公司公司員工Id分別是:" ); foreach (var item in datas) { Console.WriteLine(+item.Id); } } }
//C#控制台調用
new HeadOfficeManager().Print(); BranchOfficeManager branchOfficeManager = new BranchOfficeManager(); branchOfficeManager.Print();
總結
迪米特原則在我們日常編碼中可能往往最容易被忽略,像案例2這樣的需求,尤其寫第一種方案的代碼的人估計不少,我也寫過,慢慢掌握了設計原則後,可以和之前寫地代碼做下對比,心中會有另一番收穫。
作者:realyrare
出處:https://www.cnblogs.com/mhg215/
聲援博主:如果您覺得文章對您有幫助,請點擊文章末尾的【關註我】吧!
別忘記點擊文章右下角的【推薦】支持一波。~~~///(^v^)\\\~~~ .
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
如果您有其他問題,也歡迎關註我下方的公眾號,可以聯繫我一起交流切磋!