目录
1、基本介绍
- 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽可能将逻辑封装在类的内部。对外除了提供的public方法,不对外泄露任何信息;
- 一个对象应该对其他对象保持最少的了解;
- 类与类关系越密切,耦合度越大;
- 迪米特法则还有个更简单的定义:只与直接的朋友通信;
- 直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
2、应用实例
2.1、需求
有校学生会成员和院学生会成员,现在需要编程打印所有学生会成员。
2.2、传统方式实现
2.2.1、类图
2.2.2、代码
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
CollegeManager collegeManager = new CollegeManager();
SchoolManager schoolManager = new SchoolManager();
schoolManager.printAllStudentCouncilMember(collegeManager);
}
}
/**
* 学校管理者
*/
class SchoolManager{
/**
* SchoolStudentCouncilMember是这个方法的返回值
* 所以SchoolStudentCouncilMember是SchoolManager的直接朋友
*/
public List<SchoolStudentCouncilMember> getAllSchoolStudentCouncilMember() {
List<SchoolStudentCouncilMember> list;
list = new ArrayList<>();
for(int i=1;i<=10;i++){
list.add(new SchoolStudentCouncilMember(i+""));
}
return list;
}
/**
* 打印所有学生会成员
*/
public void printAllStudentCouncilMember(CollegeManager collegeManager){
System.out.println("---------校学生会----------");
List<SchoolStudentCouncilMember> list1 = getAllSchoolStudentCouncilMember();
for(SchoolStudentCouncilMember s : list1){
System.out.println("校学生会:"+s.getId());
}
System.out.println("----------院学生会-----------");
/**
* CollegeStudentCouncilMember是局部变量
* 所以CollegeStudentCouncilMember不是SchoolManager的直接朋友
* 违反了迪米特法则
*/
List<CollegeStudentCouncilMember> list2 = collegeManager.getAllCollegeStudentCouncilMember();
for(CollegeStudentCouncilMember c : list2){
System.out.println("院学生会:"+c.getId());
}
}
}
/**
* 学院管理者
*/
class CollegeManager{
public List<CollegeStudentCouncilMember> getAllCollegeStudentCouncilMember() {
List<CollegeStudentCouncilMember> collegeStudentCouncilMemberList;
collegeStudentCouncilMemberList = new ArrayList<>();
for(int i=11;i<=20;i++){
collegeStudentCouncilMemberList.add(new CollegeStudentCouncilMember(i+""));
}
return collegeStudentCouncilMemberList;
}
}
/**
* 校学生会成员
*/
class SchoolStudentCouncilMember{
private String id;
public SchoolStudentCouncilMember(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
/**
* 院学生会成员
*/
class CollegeStudentCouncilMember{
private String id;
public CollegeStudentCouncilMember(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
运行结果:
2.2.3、传统方式实现分析
传统方式解决了问题,但是却违反了迪米特法则。
SchoolManager中的printAllStudentCouncilMember()方法中以局部变量的方式引用了CollegeStudentCouncilMember类,所以在这里CollegeStudentCouncilMember不是SchoolManager的直接朋友。
解决方式:将CollegeStudentCouncilMember变成SchoolManager的直接朋友,可以通过构造器传入、setter方法设置、参数传入等方式解决。
2.3、遵循迪米特法则实现
2.3.1、类图
说明:类图与原来的差别不大,只是将院学生会成员的打印细节封装到了院管理者内部,对外只暴露出一个printCollegeStudentCouncilMembel()方法。
2.3.2、代码
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
CollegeManager collegeManager = new CollegeManager();
SchoolManager schoolManager = new SchoolManager();
schoolManager.printAllStudentCouncilMember(collegeManager);
}
}
/**
* 学校管理者
*/
class SchoolManager{
/**
* SchoolStudentCouncilMember是这个方法的返回值
* 所以SchoolStudentCouncilMember是SchoolManager的直接朋友
*/
public List<SchoolStudentCouncilMember> getAllSchoolStudentCouncilMember() {
List<SchoolStudentCouncilMember> list;
list = new ArrayList<>();
for(int i=1;i<=10;i++){
list.add(new SchoolStudentCouncilMember(i+""));
}
return list;
}
/**
* 打印所有学生会成员
*/
public void printAllStudentCouncilMember(CollegeManager collegeManager){
System.out.println("---------校学生会----------");
List<SchoolStudentCouncilMember> list1 = getAllSchoolStudentCouncilMember();
for(SchoolStudentCouncilMember s : list1){
System.out.println("校学生会:"+s.getId());
}
//打印院学生会
collegeManager.printCollegeStudentCouncilMembel();
}
}
/**
* 学院管理者
*/
class CollegeManager{
public List<CollegeStudentCouncilMember> getAllCollegeStudentCouncilMember() {
List<CollegeStudentCouncilMember> collegeStudentCouncilMemberList;
collegeStudentCouncilMemberList = new ArrayList<>();
for(int i=11;i<=20;i++){
collegeStudentCouncilMemberList.add(new CollegeStudentCouncilMember(i+""));
}
return collegeStudentCouncilMemberList;
}
/**
* 打印院学生会
*/
public void printCollegeStudentCouncilMembel(){
List<CollegeStudentCouncilMember> list = getAllCollegeStudentCouncilMember();
System.out.println("----------院学生会-----------");
for(CollegeStudentCouncilMember c : list){
System.out.println("院学生会:"+c.getId());
}
}
}
/**
* 校学生会成员
*/
class SchoolStudentCouncilMember{
private String id;
public SchoolStudentCouncilMember(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
/**
* 院学生会成员
*/
class CollegeStudentCouncilMember{
private String id;
public CollegeStudentCouncilMember(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
运行结果与上面相同。
2.3.3、迪米特法则实现分析
将学院管理者与学校管理者两个类之间的耦合度降到了最低。学校管理者只需要调用打印院学生会成员的方法,而不需要知道其打印细节,这样提高了程序的可靠性。
3、迪米特法则注意事项和细节
- 迪米特法则的核心是降低类之间的耦合
- 但是注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系。