翼度科技»论坛 编程开发 .net 查看内容

必知必会的设计原则——迪米特原则

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
 设计原则系列文章 

必知必会的设计原则——接口隔离原则
必知必会的设计原则——单一职责原则
必知必会的设计原则——开放封闭原则
必知必会的设计原则——依赖倒置原则
必知必会的设计原则——里氏替换原则
概述

迪米特法则(Law of Demeter )又叫做最少知识原则,即一个对象应该对另一个对象有最少的了解。
迪米特法则的目的在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。
迪米特原则实际上就是一个类在创建方法和属性时要遵守的法则;
迪米特原则核心指导思想为只和直接朋友通信(成员对象、方法参数、方法返回值;值出现在局部变量的类 ,不是直接朋友)。
案例需求1

实现人关机电脑(人关机电脑一般最起码分为三个步骤,第一步先保存当前的任务,第二步关闭屏幕,第三步关机电源)。
未使用迪米特原则的代码
  1.   public class Computer
  2.     {   
  3.         public void SaveTask()
  4.         {
  5.             Console.WriteLine("保存当前电脑任务");
  6.         }
  7.         public void CloseScreen()
  8.         {
  9.             Console.WriteLine("关闭屏幕");
  10.         }
  11.         public void ShutDown()
  12.         {
  13.             Console.WriteLine("关闭电源");
  14.         }      
  15.     }
  16.     public class Person
  17.     {
  18.         public void CloseComputer(Computer computer)
  19.         {computer.SaveTask();   
  20.             computer.CloseScreen();
  21.             computer.ShutDown();
  22.         }
  23.     }
复制代码
上面person类中的CloseComputer方法中逻辑不符合迪米特原则,如果关机需要三十步,computer需要提供30个方法,每个方法之间都有相应的绝对顺序
使用迪米特原则的代码
  1.   public class Computer
  2.     {
  3.         public void SaveTask()
  4.         {
  5.             Console.WriteLine("保存当前电脑任务");
  6.         }
  7.         public void CloseScreen()
  8.         {
  9.             Console.WriteLine("关闭屏幕");
  10.         }
  11.         public void ShutDown()
  12.         {
  13.             Console.WriteLine("关闭电源");
  14.         }
  15.         public  void CloseComputer()
  16.         {
  17.             this.SaveTask();
  18.             this.CloseScreen();
  19.             this.ShutDown();
  20.         }
  21.     }
  22.   //person类中closecomputer方法中的参数computer为直接朋友,符合迪米特原则
  23.     public class Person
  24.     {
  25.         public void CloseComputer(Computer computer)
  26.         {           
  27.             computer.CloseComputer();
  28.         }
  29.     }
复制代码
上面person类中的CloseComputer方法只负责调用Computer中的CloseComputer方法,如果关机电脑这个需求有其他的变化,computer类里面添加方法或发生逻辑变化,person类始终不会发生改变。
关于迪米特原则很多人听到这个词,估计有点陌生,真实编程中可能这样用过,但不知道其名字,所以我们再来看一个案例需求,加深巩固理解。
案例需求2

分别打印总公司和分公司员工的编号;
未使用迪米特原则的代码    
  1.     public class HeadOfficeEmployee
  2.     {
  3.         public int Id { get; set; }
  4.     }
  5.     /// <summary>
  6.     /// 总公司管理者
  7.     /// </summary>
  8.     public class HeadOfficeManager
  9.     {
  10.         /// <summary>
  11.         /// 获取员工数
  12.         /// </summary>
  13.         /// <returns></returns>
  14.         public List<HeadOfficeEmployee> GetEmployees()
  15.         {
  16.         List<HeadOfficeEmployee> headOffices = new List<HeadOfficeEmployee>();
  17.             for (int i = 0; i < 10; i++)
  18.             {
  19.                 HeadOfficeEmployee headOfficeEmployee = new HeadOfficeEmployee();
  20.                 headOfficeEmployee.Id = i;
  21.                 headOffices.Add(headOfficeEmployee);
  22.             }
  23.             return headOffices;
  24.         }
  25.         /// <summary>
  26.         /// 打印总公司员工id
  27.         /// </summary>
  28.         public void Print(BranchOfficeManager branchOfficeManager)
  29.         {
  30.           var datas=  GetEmployees();
  31.             Console.WriteLine("总公司员工Id分别是:" );
  32.             foreach (var item in datas)
  33.             {
  34.                 Console.WriteLine(+item.Id);
  35.             }
  36.       //branchOfficeEmployes这个集合对象,是通过局部变量的形式出现在类中的,所以不是我们的直接朋友,故不符合迪米特原则。
  37.            var branchOfficeEmployes= branchOfficeManager.GetEmployees();
  38.             Console.WriteLine("分公司员工Id分别是:");
  39.             foreach (var item in branchOfficeEmployes)
  40.             {
  41.                 Console.WriteLine(+item.Id);
  42.             }
  43.         }
  44.     }
复制代码
  1. //C# 控制台调用
  2. BranchOfficeManager branchOfficeManager = new BranchOfficeManager();
  3. new HeadOfficeManager().Print(branchOfficeManager);
复制代码
以上HeadOfficeManager类中Print方法传递的参数branchOfficeManager是直接朋友,GetEmployee()中返回的集合对象也是直接朋友符合迪米特原则,但branchOfficeManager.GetEmployees()获取的集合branchOfficeEmployes是通过局部变量的形式出现在类中的,所以不符合迪米特原则。
 使用迪米特原则改造后的代码 
  1.     /// <summary>
  2.     /// 总公司员工
  3.     /// </summary>
  4.     public class HeadOfficeEmployee
  5.     {
  6.         public int Id { get; set; }
  7.     }
  8.     /// <summary>
  9.     /// 总公司管理者
  10.     /// </summary>
  11.     public class HeadOfficeManager
  12.     {
  13.         /// <summary>
  14.         /// 获取员工数
  15.         /// </summary>
  16.         /// <returns></returns>
  17.         public List<HeadOfficeEmployee> GetEmployees()
  18.         {
  19.         List<HeadOfficeEmployee> headOffices = new List<HeadOfficeEmployee>();
  20.             for (int i = 0; i < 10; i++)
  21.             {
  22.                 HeadOfficeEmployee headOfficeEmployee = new HeadOfficeEmployee();
  23.                 headOfficeEmployee.Id = i;
  24.                 headOffices.Add(headOfficeEmployee);
  25.             }
  26.             return headOffices;
  27.         }
  28.         /// <summary>
  29.         /// 打印总公司员工id
  30.         /// </summary>
  31.         public void Print()
  32.         {
  33.           var datas=  GetEmployees();
  34.             Console.WriteLine("总公司员工Id分别是:" );
  35.             foreach (var item in datas)
  36.             {
  37.                 Console.WriteLine(+item.Id);
  38.             }           
  39.         }<br>}
复制代码
  1.    /// <summary>
  2.     /// 分公司员工类
  3.     /// </summary>
  4.     public class BranchOfficeEmployee
  5.     {
  6.         public int Id { get; set; }
  7.     }
  8.     /// <summary>
  9.     /// 分公司员工管理者
  10.     /// </summary>
  11.     public class BranchOfficeManager
  12.     {
  13.         public List<BranchOfficeEmployee> GetEmployees()
  14.         {
  15.         List<BranchOfficeEmployee> headOffices = new List<BranchOfficeEmployee>();
  16.             for (int i = 0; i < 10; i++)
  17.             {
  18.                 BranchOfficeEmployee headOfficeEmployee = new BranchOfficeEmployee();
  19.                 headOfficeEmployee.Id = i;
  20.                 headOffices.Add(headOfficeEmployee);
  21.             }
  22.             return headOffices;
  23.         }
  24.         /// <summary>
  25.         /// 打印分公司每个员工Id
  26.         /// </summary>
  27.         public void Print()
  28.         {
  29.           var datas=  GetEmployees();
  30.             Console.WriteLine("分公司公司员工Id分别是:" );
  31.             foreach (var item in datas)
  32.             {
  33.                 Console.WriteLine(+item.Id);
  34.             }
  35.         }
  36.     }
复制代码
  1. //C#控制台调用<br>new HeadOfficeManager().Print();
  2. BranchOfficeManager branchOfficeManager = new BranchOfficeManager();
  3. branchOfficeManager.Print();  
复制代码
总结

迪米特原则在我们日常编码中可能往往最容易被忽略,像案例2这样的需求,尤其写第一种方案的代码的人估计不少,我也写过,慢慢掌握了设计原则后,可以和之前写地代码做下对比,心中会有另一番收获。

来源:https://www.cnblogs.com/mhg215/archive/2023/02/13/17108461.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具