定义
迪米特法则又称最少知识原则(Least Knowledge Principle, LKP)
只与你的直接朋友交谈,不跟“陌生人”说话
Talk only to your immediate friends and not to strangers
其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。
迪米特法则的优点
迪米特法则要求限制软件实体之间通信的宽度和深度,正确使用迪米特法则将有以下两个优点。
- 降低了类之间的耦合度,提高了模块的相对独立性。
- 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
使用迪米特法则的平衡
过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低。所以,在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。
迪米特法则的实现方法
从迪米特法则的定义和特点可知,它强调以下两点:
- 从依赖者的角度来说,只依赖应该依赖的对象。
- 从被依赖者的角度说,只暴露应该暴露的方法。
案例:手机读书
需求:平常在零碎的时间里,喜欢看一些书籍,一般都是电子书,现在我们看书的操作是这样的:唤醒手机,打开阅读软件,选择书籍,然后阅读。总共 3 个步骤,涉及了 3 样东西:手机、软件、书籍。
可能会产生如下代码:
// 测试类
public class Test {
public static void main(String[] args) {
Phone phone = new Phone();
phone.readBook();
}
}
// 手机类
class Phone {
App app = new App();
Book book = new Book("设计模式");
public void readBook() {
app.read(book);
}
}
// app类
class App {
public void read(Book book) {
System.out.println(book.getTitle());
}
}
// 书类
class Book {
private String title;
public Book(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
代码是完成了读书这个过程,看样子是功能实现了,细看会发现代码的逻辑不对。哪里不对呢?书籍和应用对象都在手机上,现实是我们唤醒手机,这时手机是没有书籍的,只有当我们打开阅读软件,才有书籍可以看,没有阅读软件,书籍是看不了的。因此,手机和书籍没有一毛钱关系,书籍不应该在手机里面。正常的设计是:手机里面有阅读软件,阅读软件里面有书籍,这才符合迪米特法则,按定义来说:手机和阅读软件是朋友,阅读软件和书籍是朋友,可是朋友的朋友不是朋友,也就是手机和书籍不是朋友,所以它们不应该有交集,应该离得远远的。
正确示例:
public class Test {
public static void main(String[] args) {
Phone phone = new Phone();
phone.readBook();
}
}
class Phone {
private App app = new App();
public void readBook() {
app.read();
}
}
class App {
private Book book = new Book("设计模式");
public void read() {
System.out.println(book.getTitle());
}
}
class Book {
private String title;
public Book(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
现在这段代码就符合迪米特法则,手机中有阅读软件,阅读软件中有书籍,手机没有书籍任何影子。
参考链接
http://c.biancheng.net/view/1331.html
https://segmentfault.com/a/1190000017779269