迪米特法则(Law of Demeter)(Demeter Principle)

一、基本介绍

  1、一个对象应该对其他对象保持最少的了解;

  2、类与类关系越密切,耦合度越大;

  3、迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外处了提供 public 方法,不对外泄漏任何信息;

  4、迪米特法则还有个简单的定义:只与直接的朋友通信;

  直接朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这个两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。

         其中,我们称出现在成员变量、方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就说说,陌生的类最好不要以局部变量的形式出现在类的内部。

  

二、应用案例

  1、需求说明

    有一个学校,下属有各个学院和总部,现要求打印出学校总部员工 ID和学院员工的 ID。

    

 

 

 

  2、方式一

    代码实现:

 1 public class Demeter1 {
 2     //客户端,使用
 3     public static void main(String[] args) {
 4         SchoolManager schoolManager = new SchoolManager();
 5         schoolManager.printAllEmployee(new CollegeManager());
 6     }
 7 }
 8 
 9 /**
10  * 学校总部员工
11  */
12 class Employee {
13     private String id;
14 
15     public void setId(String id) {
16         this.id = id;
17     }
18 
19     public String getId() {
20         return id;
21     }
22 }
23 
24 /**
25  * 学院的员工
26  */
27 class CollegeEmployee {
28     private String id;
29 
30     public void setId(String id) {
31         this.id = id;
32     }
33 
34     public String getId() {
35         return id;
36     }
37 }
38 
39 /**
40  * 管理学院员工的管理类
41  */
42 class CollegeManager {
43     //返回学院的所有员工
44     public List<CollegeEmployee> getAllEmployee() {
45         List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
46         for (int i = 0; i < 10; i++) {
47             CollegeEmployee emp = new CollegeEmployee();
48             emp.setId("学院员工id= " + i);
49             list.add(emp);
50         }
51         return list;
52     }
53 }
54 
55 /**
56  * 学校的管理类
57  *  分析:
58  *      直接朋友类:Employee、CollegeManager
59  *      间接朋友类:CollegeEmployee,是一个陌生类,违反了迪米特法则
60  */
61 class SchoolManager {
62     //返回学校总部的员工
63     public List<Employee> getAllEmployee() {
64         List<Employee> list = new ArrayList<Employee>();
65 
66         for (int i = 0; i < 5; i++) {
67             Employee emp = new Employee();
68             emp.setId("学校总部员工id= " + i);
69             list.add(emp);
70         }
71         return list;
72     }
73 
74     //输出学校总部和学院员工的信息
75     void printAllEmployee(CollegeManager sub) {
76 
77         /*  分析:
78             1、CollegeEmployee 不是 SchoolManager 的直接朋友
79             2、CollegeEmployee 是以布局变量出现在 SchoolManager
80             3、违反了迪米特法则
81          */
82         List<CollegeEmployee> list1 = sub.getAllEmployee();
83         System.out.println("------------学院员工------------");
84         for (CollegeEmployee e : list1) {
85             System.out.println(e.getId());
86         }
87         List<Employee> list2 = this.getAllEmployee();
88         System.out.println("------------学校总部员工------------");
89         for (Employee e : list2) {
90             System.out.println(e.getId());
91         }
92     }
93 }

 

    分析:

    (1)前面设计的问题在于 SchoolManager 中,CollegeEmployee 类并不是 SchoolManager  类的直接朋友;

    (2)按照迪米特法则,应该避免类中出现这样非直接朋友的耦合;

    (3)对代码按照迪米特法则,进行改进;

  3、方式二

    代码实现:

 1 public class Demeter1 {
 2     //客户端,使用
 3     public static void main(String[] args) {
 4         System.out.println("~~~使用迪米特法则的改进~~~");
 5         SchoolManager schoolManager = new SchoolManager();
 6         schoolManager.printAllEmployee(new CollegeManager());
 7     }
 8 }
 9 
10 /**
11  * 学校总部员工
12  */
13 class Employee {
14     private String id;
15 
16     public void setId(String id) {
17         this.id = id;
18     }
19 
20     public String getId() {
21         return id;
22     }
23 }
24 
25 /**
26  * 学院的员工
27  */
28 class CollegeEmployee {
29     private String id;
30 
31     public void setId(String id) {
32         this.id = id;
33     }
34 
35     public String getId() {
36         return id;
37     }
38 }
39 
40 /**
41  * 管理学院员工的管理类
42  */
43 class CollegeManager {
44     //返回学院的所有员工
45     public List<CollegeEmployee> getAllEmployee() {
46         List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
47         for (int i = 0; i < 10; i++) {
48             CollegeEmployee emp = new CollegeEmployee();
49             emp.setId("学院员工id= " + i);
50             list.add(emp);
51         }
52         return list;
53     }
54 
55     //输出学院员工的信息
56     public void printCollageEmployee() {
57         List<CollegeEmployee> list1 = getAllEmployee();
58         System.out.println("------------学院员工------------");
59         for (CollegeEmployee e : list1) {
60             System.out.println(e.getId());
61         }
62     }
63 
64 }
65 
66 /**
67  * 学校的管理类
68  *  分析:
69  *      直接朋友类:Employee、CollegeManager
70  *      间接朋友类:CollegeEmployee,是一个陌生类,违反了迪米特法则
71  */
72 class SchoolManager {
73     //返回学校总部的员工
74     public List<Employee> getAllEmployee() {
75         List<Employee> list = new ArrayList<Employee>();
76 
77         for (int i = 0; i < 5; i++) {
78             Employee emp = new Employee();
79             emp.setId("学校总部员工id= " + i);
80             list.add(emp);
81         }
82         return list;
83     }
84 
85     //输出学校总部和学院员工的信息
86     void printAllEmployee(CollegeManager sub) {
87 
88         //1.将输出学院的员工的方法,封装到 CollegeManager 类中
89         sub.printCollageEmployee();
90         //2.输出学校总部的员工信息
91         List<Employee> list2 = this.getAllEmployee();
92         System.out.println("------------学校总部员工------------");
93         for (Employee e : list2) {
94             System.out.println(e.getId());
95         }
96     }
97 }

 

 

三、小结

  1、迪米特法则的核心是降低类之间的耦合;

  2、但是注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系;

 

posted on 2020-12-29 21:08  格物致知_Tony  阅读(238)  评论(0编辑  收藏  举报