# 迪米特法则(Law of Demeter)
基本介绍:
一个对象应该改对其他对象保持最少的了解
类与类的关系越密切,耦合度越大
迪米特法则又叫最少知道原则,简单说就是一个类对自己依赖的类知道的越少越好,被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部,对外只提供public方法,不对外泄露任何信息。
迪米特法则有个更简单的定义:只与直接朋友通信
直接朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,就可以说这两个对象之间是朋友关系。其中,出现的成员变量,方法参数,方法返回值中的类称为直接朋友。而出现在局部变量中的类不是直接朋友,也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
# 迪米特法则例子
有一个学校,下属有各个学院和总部,现要求打印出学校总部员工ID和学院员工的ID
import java.util.ArrayList;
import java.util.List;
//客户端
public class Main {
public static void main(String[] args) {
SchoolManager schoolManager = new SchoolManager();
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++) {
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工id:" + i);
list.add(emp);
}
return list;
}
}
//管理学校员工
class SchoolManager {
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<Employee>();
for(int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学校总部员工:" + i);
list.add(emp);
}
return list;
}
//打印所有的员工
void printAllEmployee(CollegeManager sub) {
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());
}
}
}
现在来分析一下这个代码,符不符合迪米特法则。
迪米特法则的规则是,一个类只与它的直接朋友进行交流,耦合类的对象的直接朋友是,成员变量,方法参数,方法返回值,除了以上三种都不是直接朋友。
来看一下这段代码,传入参数的类型是CollegeManager
,按照规则它是本类的直接朋友,再看CollegeEmployee
他们在方法体中,是局部变量,所以并不是本类的直接朋友。为什么Employee
是直接朋友?那是因为在上一个方法中Employee
是作为方法返回值使用的。那么CollegeEmployee
这部分代码放到哪里呢?传入参数是sub
,所以相当于把输出这件事情交给了sub
去处理,所以把他们封装到CollegeManager
中。
void printAllEmployee(CollegeManager sub) {
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());
}
}
改正代码后,其实代码逻辑也更符合现实生活一点,因为一个学院总会有自己学院员工名单的,不可能什么都交给学校去做,而一个学校的权力肯定比学院要大一点,有权去知道这个学院有多少员工。
import java.util.ArrayList;
import java.util.List;
//客户端
public class Main {
public static void main(String[] args) {
SchoolManager schoolManager = new SchoolManager();
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++) {
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工id:" + i);
list.add(emp);
}
return list;
}
public void printAllEmployee() {
List<CollegeEmployee> list1 = this.getAllEmployee();
System.out.println("---------学院员工----------");
for(CollegeEmployee e : list1) {
System.out.println(e.getId());
}
}
}
//管理学校员工
class SchoolManager {
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<Employee>();
for(int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学校总部员工:" + i);
list.add(emp);
}
return list;
}
//打印所有的员工
void printAllEmployee(CollegeManager sub) {
sub.printAllEmployee();
List<Employee> list2 = this.getAllEmployee();
System.out.println("----------学校总部员工--------");
for (Employee e : list2) {
System.out.println(e.getId());
}
}
}