迪米特法则是在一个叫做迪米特的项目中提出来的,它要求一个对象应该对其他对象有最少的了解,所以迪米特法则又叫做最少知识原则。
迪米特法则的意义是降低类之间的耦合,由于每个对象应该尽量减少对其他对象的了解,因此,很容易使得系统的功能模块独立,相互之间不存在或者很少的依赖关系。
那么怎么做到一个对象对其他对象的了解最少呢?我们把对象比作我们自己,要想实现对其他人有更少的了解,做到两点就够了:1. 只和直接的朋友交流;2.减少对朋友的了解。
迪米特法则有一个英文解释:talk only to your immediate friends。每个对象都必然会与其他对象有耦合关系,两个对象之间有耦合,就会成为朋友,而出现在成员变量、方法参数和返回值中的对象就是直接的朋友。
迪米特法则要求只与直接的朋友进行通信。
在方法体内部出现的类就不是直接的朋友,如果一个类不是和直接朋友进行交流,那么就违反了迪米特法则。
下面我们以一个统计学生的例子来对迪米特法则的实际应用进行讲解。
学生类:
class Student {
}
班长类:
class GroupLeader {
public void count(ArrayList students) {
System.out.println(students.size());
}
}
教师类:
class Teacher {
public void command(GroupLeader groupLeader) {
ArrayList students = new ArrayList<>();
for (int i = 0; i < 20; i++) {
students.add(new Student());
}
groupLeader.count(students);
}
}
应用场景:
public static void main(String[] args) {
new Teacher().command(new GroupLeader());
}
分析Teacher类,发现Teacher类总共有GroupLeader和Student两个朋友,GroupLeader是Teacher类方法的参数,因此GroupLeader类是Teacher类的之间朋友,而Student不是Teacher类的直接朋友,且Student类在Teacher类的方法中被使用,因此Teacher违背了迪米特法则只与直接朋友交流的原则。
因此我们需要在Teacher类中移除Student类的使用,可行的方法是将其处理放到GroupLeader类中。
class GroupLeader {
private ArrayList students;
public GroupLeader() {
students = new ArrayList<>();
for (int i = 0; i < 20; i++) {
students.add(new Student());
}
}
public void count() {
System.out.println(students.size());
}
}
其实我们同样可以将students声明为Teacher类的成员变量,但是这样的话,Student类同时与Teacher类与GroupLeader类存在依赖,而迪米特法则要求低耦合,因此将students作为GroupLeader类的成员变量使得Student类只与GroupLeader类存在依赖,与Teacher类不存在依赖。
迪米特法则同样要求减少对朋友的了解。具体的实现方法就是减少一个类对外暴露的方法,在Java语言中具体就是减少Public方法。
下面以咖啡机为例子讲解如何减少对朋友的了解。
咖啡机类:
class CoffeeMachine {
public void addCoffeeBean() {
System.out.println("添加咖啡豆");
}
public void addWater() {
System.out.println("添加水");
}
public void makeCoffee() {
System.out.println("制作咖啡");
}
}
人类:
class Person {
public void makeCoffee(CoffeeMachine coffeeMachine) {
coffeeMachine.addCoffeeBean();
coffeeMachine.addWater();
coffeeMachine.makeCoffee();
}
}
人类关心的事情仅仅是让咖啡机制作咖啡,并不关系咖啡是如何制作的,提供较多的开放方法增加了两个类之间的耦合程度,不利于咖啡机类的扩展,假如我们改进了咖啡机的制作工艺,可以自动地加牛奶,这时候,用户需要修改自己地代码。
修改咖啡机类为仅仅对外暴露一个make方法用于制作咖啡,用户仅仅需要调用这个方法就可以制作咖啡。
public void make() {
addCoffeeBean();
addWater();
makeCoffee();
}
人类:
class Person {
public void makeCoffee(CoffeeMachine coffeeMachine) {
coffeeMachine.make();
}
}
迪米特法则的目的,是把我们的类变成一个个“肥宅”。
迪米特法则的核心观念就是类间解耦,弱耦合。只有弱耦合了之后,类的复用才可以提高,类变更的风险才可以减低。但解耦是有限度的,除非是计算机的最小单元--二进制的0和1,否则都是存在耦合的。所以在实际项目中,需要适度地参考这个原则,避免过犹不及。六大设计原则之五:迪米特法则www.jianshu.com