设计模式:7.设计模式的七大原则之六(迪米特法则)

101 阅读3分钟

迪米特法则(Demeter Princlple)

1.基本介绍
  • 一个对象应该对其他对象保持最小的了解
  • 类与类关系越密切,耦合度越大
  • 迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。
  • 对于被依赖的类不管多复杂,都尽量将逻辑封装在类的内部,对外除了提供的public方法,不对外泄露任何信息。
  • 只与直接的朋友通信。
  • 什么是直接的朋友?:每个对象都会与其他对象有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式有很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。

简单来说,就是最好不要出现以下情况

class A{
	public void func1(){
		B b = new B();	// 陌生的B类以局部变量的形式出现在了类内部
	}
}
2.一个违反迪米特的实际案例

一个学校,员工分为学校管理层和各个学院老师,要求先打印出学校管理层的员工ID再打印出各个学院老师的ID。

/*
* 学校管理层员工实体类
*/
class ManagerEmployee(){
	// 员工ID
	private String id;
	
	public void setId(String id){ this.id = id }
	public String getId(){ return id }
}

/*
* 学院老师实体类
*/
class TeacherEmployee(){
	// 员工ID
	private String id;
	
	public void setId(String id){ this.id = id }
	public String getId(){ return id }
}

/*
* 学校管理层员工数据源,模拟构造3个学校管理人员
*/
class ManagerEmployeeDataSource(){
	public List<ManagerEmployee> getAllManagerEmployee(){
		List<ManagerEmployee> managers = new ArraryList<>();
		for(int 1=0; i<3; i++){
			ManagerEmployee m = new ManagerEmployee();
			m.setId(i);
			managers.add(m);
		}
		return managers ;
	}
}

/*
* 学院老师员工数据源,模拟构造5个学院老师人员
* 同时还有打印学校管理层及学院老师信息的方法
*/
class TeacherEmployeeDataSource(){
	// 构造老师信息
	public List<TeacherEmployee> getAllTeacherEmployee(){
		List<TeacherEmployee> teachers = new ArraryList<>();
		for(int 1=0; i<5; i++){
			TeacherEmployeem t = new TeacherEmployee();
			t.setId(i);
			teachers.add(t);
		}
		return teachers;
	}

	// 打印信息
	public void printAll(ManagerEmployeeDataSource mds){
		List<ManagerEmployee> managers = mds.getAllManagerEmployee();
		sout("------管理层信息------");
		for(ManagerEmployee m : managers ){
			sout(m.getId());
		}
		
		List<TeacherEmployee> teachers = this.getAllTeacherEmployee();
		sout("------学院老师信息------");
		for(TeacherEmployee t: teachers){
			sout(t.getId());
		}
	}
}

public Do{
	public static void main(){
		TeacherEmployeeDataSource ts = new TeacherEmployeeDataSource();
		ts.printAll(new ManagerEmployeeDataSource());
	}
}

先分析一下以上的代码中哪些是直接朋友:
在这里插入图片描述
ManagerEmployee不是类TeacherEmployeeDataSource的直接朋友,所以违背了迪米特法则。

3.符合迪米特法则的修改

改进的思路:以上的问题是学校管理层类ManagerEmployee类不是学院老师数据构造类TeacherEmployeeDataSource类的直接朋友,违背了迪米特法则,即要避免出现这种情况。

  • 将打印学校管理层信息的代码挪到学校管理层数据构造类中
    这里也就是我们开头说的对于被依赖的类不管多复杂,都尽量将逻辑封装在类的内部,对外除了提供的public方法,不对外泄露任何信息
/*
* 学校管理层员工数据源,模拟构造3个学校管理人员
*/
class ManagerEmployeeDataSource(){
	public List<ManagerEmployee> getAllManagerEmployee(){
		List<ManagerEmployee> managers = new ArraryList<>();
		for(int 1=0; i<3; i++){
			ManagerEmployee m = new ManagerEmployee();
			m.setId(i);
			managers.add(m);
		}
		return managers ;
	}

	// 打印信息
	public void printAllManager(){
		List<ManagerEmployee> managers = getAllManagerEmployee();
		sout("------管理层信息------");
		for(ManagerEmployee m : managers ){
			sout(m.getId());
		}
	}
}
  • 学院老师数据构造类中保留打印学院老师信息的代码
/*
* 学院老师数据源,模拟构造5个学院老师
*/
class TeacherEmployeeDataSource(){
	// 构造老师信息
	public List<TeacherEmployee> getAllTeacherEmployee(){
		List<TeacherEmployee> teachers = new ArraryList<>();
		for(int 1=0; i<5; i++){
			TeacherEmployeem t = new TeacherEmployee();
			t.setId(i);
			teachers.add(t);
		}
		return teachers;
	}

	// 打印信息
	public void printAll(ManagerEmployeeDataSource mds){
		// 打印所有管理层
		mds.printAllManager();
		// 打印所有学院老师
		List<TeacherEmployee> teachers = getAllTeacherEmployee();
		sout("------学院老师信息------");
		for(TeacherEmployee t: teachers){
			sout(t.getId());
		}
	}
}
  • 使用不需要修改
public Do{
	public static void main(){
		TeacherEmployeeDataSource ts = new TeacherEmployeeDataSource();
		ts.printAll(new ManagerEmployeeDataSource());
	}
}
  • 再来分析下之前违背迪米特法则的代码
    在这里插入图片描述