05-迪米特法则(LOD 又名: 最少知道原则)

时间:2023-03-08 16:27:17

1. 背景

     类与类之间的关系越密切,耦合度越大,当一个类发生变化时,对另一个类的影响也越大。

2. 定义

    一个类应该对其它类保持最少的了解。

3. 解决方法

     尽量降低类与类之间的耦合。

4. 迪米特法则的核心

      低耦合

5.迪米特法则深究

  只与直接的朋友通信。
   每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。
     耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友, 而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。

6. 模拟业务场景

  有一个集团公司,下面有很多分公司,现在要求,总公司打印出所有分公司员工的信息。剖析:总公司有很多员工(Employee),分公司里也有很多员工(SubEmployee);总公司与公司的员工、总公司与分公司、分公司与分公司的员工是直接朋友;总公司和分公司的员工不是直接朋友。

先看一个违反了迪米特法则的设计方式:

     /// <summary>
/// 总公司员工类
/// </summary>
public class Employee
{
private string id;
public void setId(string id)
{
this.id = id;
}
public string getId()
{
return id;
}
}
     /// <summary>
/// 分公司员工类
/// </summary>
public class SubEmployee
{
private string id;
public void setId(string id)
{
this.id = id;
}
public string getId()
{
return id;
}
}
     /// <summary>
/// 分公司管理类
/// </summary>
public class SubCompanyManager
{
/// <summary>
/// 获取分公司员工信息
/// </summary>
/// <returns></returns>
public List<SubEmployee> getAll()
{
List<SubEmployee> list = new List<SubEmployee>();
for (int i = ; i < ; i++)
{
SubEmployee sel = new SubEmployee();
sel.setId("分公司员工" + i);
list.Add(sel);
}
return list;
} }
 /// <summary>
/// 总公司管理类
/// </summary>
public class CompanyManager
{
/// <summary>
/// 获取总公司员工信息
/// </summary>
/// <returns></returns>
public List<Employee> getAll()
{
List<Employee> list = new List<Employee>();
for (int i = ; i < ; i++)
{
Employee sel = new Employee();
sel.setId("总公司公司员工" + i);
list.Add(sel);
}
return list;
}
/// <summary>
/// 打印总公司员工信息
/// </summary>
public void printEmployee()
{
foreach (var item in this.getAll())
{
Console.WriteLine(item.getId());
}
}
/// <summary>
/// 打印分公司员工信息
/// </summary>
public void printSubEmployee(SubCompanyManager sub)
{
//这里违背了迪米特法则,直接操控了分公司的员工,总公司和分公司员工不应该是直接关系
foreach (var item in sub.getAll())
{
Console.WriteLine(item.getId());
}
} }
    public static void show()
{
//模拟业务场景:有一个集团公司,下面有很多分公司,现在要求,总公司打印出所有分公司员工的信息。
//剖析:总公司有很多员工(Employee),分公司里也有很多员工(SubEmployee);总公司与公司的员工、总公司与分公司、分公司与分公司的员工是直接朋友;
//总公司和分公司的员工不是直接朋友 //下面先看一个违反了迪米特法则的设计:总公司管理类CompanyManager中直接操作了分公司的员工。
//printSubEmployee方法中违背了迪比特法则,违背了迪米特法则,直接操控了分公司的员工,总公司和分公司不应该是直接关系
CompanyManager cManager = new CompanyManager();
cManager.printSubEmployee(new SubCompanyManager()); }

总结:总公司管理类CompanyManager中直接操作了分公司的员工。printSubEmployee方法中违背了迪比特法则,违背了迪米特法则,直接操控了分公司的员工,总公司和分公司不应该是直接关系。

改进后的设计:给SubCompanyManager类中添加打印分公司员工的方法,然后再CompanyManager中,直接调用打印分公司员工的方法,这样就是总公司依赖了分公司,得到了分公司员工的信息,并没有直接依赖分公司员工。

     /// <summary>
/// 分公司管理类
/// </summary>
public class SubCompanyManager
{
/// <summary>
/// 获取分公司员工信息
/// </summary>
/// <returns></returns>
public List<SubEmployee> getAll()
{
List<SubEmployee> list = new List<SubEmployee>();
for (int i = ; i < ; i++)
{
SubEmployee sel = new SubEmployee();
sel.setId("分公司员工" + i);
list.Add(sel);
}
return list;
} /// <summary>
/// 新增:打印分公司员工信息,为了满足迪米特法则
/// </summary>
public void printSubEmployee()
{
foreach (var item in this.getAll())
{
Console.WriteLine(item.getId());
}
} }
     /// <summary>
/// 总公司管理类
/// </summary>
public class CompanyManager
{
/// <summary>
/// 打印分公司员工信息2
/// </summary>
public void printSubEmployee2(SubCompanyManager sub)
{
//这里总公司直接依赖分公司,得到了分公司员工信息,遵循了迪米特法则
sub.printSubEmployee();
} }
    public static void show()
{
//模拟业务场景:有一个集团公司,下面有很多分公司,现在要求,总公司打印出所有分公司员工的信息。
//剖析:总公司有很多员工(Employee),分公司里也有很多员工(SubEmployee);总公司与公司的员工、总公司与分公司、分公司与分公司的员工是直接朋友;
//总公司和分公司的员工不是直接朋友 //下面先看一个违反了迪米特法则的设计:总公司管理类CompanyManager中直接操作了分公司的员工。
//printSubEmployee方法中违背了迪比特法则,违背了迪米特法则,直接操控了分公司的员工,总公司和分公司不应该是直接关系
CompanyManager cManager = new CompanyManager();
cManager.printSubEmployee(new SubCompanyManager()); //下面是改进后的方案,遵循迪米特法则,给SubCompanyManager类中添加打印分公司员工的方法,然后再CompanyManager中,直接调用打印分公司员工的方法
//这样就是总公司依赖了分公司,得到了分公司员工的信息,并没有直接依赖分公司员工 Console.WriteLine("--------------------下面是采用迪米特法则改进后的方案-----------------------");
cManager.printSubEmployee2(new SubCompanyManager()); }

05-迪米特法则(LOD 又名: 最少知道原则)