「撸一手好代码」设计模式之迪米特法则
迪米特法则(Law of Demeter,LoD),也被称为最少知识原则。这一原则旨在指导我们如何设计模块间的交互,以减少模块间的耦合度,提升系统的可维护性和可扩展性。接下来,我们将深入了解迪米特法则的定义、重要性、应用场景,以及如何在实际项目中应用它。
什么是迪米特法则
迪米特法则核心思想是:
- 一个对象应该对其他对象有尽可能少的了解。
- 只与你的直接朋友通信。
这里的“直接朋友”指的是直接依赖的对象,包括:
- 当前对象本身
- 以参数形式传入到当前对象方法中的对象
- 当前对象所创建的对象
- 当前对象的直接成员对象
遵循迪米特法则,意味着我们应该尽量减少对象之间的直接依赖,降低系统的耦合度。
为什么需要迪米特法则
在软件开发中,模块间的紧密耦合往往会导致以下问题:
- 难以维护:当一个模块发生变化时,可能会影响到与之紧密耦合的其他模块。
- 难以测试:高耦合的系统在测试时,需要更多的mock和stub来模拟依赖对象。
- 难以扩展:增加新功能或修改现有功能时,可能需要修改多个模块。
迪米特法则通过限制对象间的直接依赖,帮助我们构建出更加松耦合、易于维护和扩展的系统。
如何应用迪米特法则
在实际开发中,应用迪米特法则可以从以下几个方面入手:
- 明确模块职责:首先,要确保每个模块都有清晰的职责划分,避免模块间职责重叠。
- 使用接口和抽象类:通过定义接口和抽象类来隐藏具体实现细节,减少模块间的直接依赖。
- 引入中介者模式:当多个对象需要相互通信时,可以考虑使用中介者模式来集中管理这些通信,从而降低对象间的直接依赖。
- 限制访问级别:合理设置类成员和方法的访问级别,避免不必要的暴露。
示例
反例
假设我们有一个Library
类,它负责管理图书。Library
类需要获取某本书的作者,通过一个书架Shelf
获取到所有的Book
进行遍历来获取。
/**
* 图书
*/
public class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
}
/**
* 书架
*/
public class Shelf {
private List<Book> books;
public Shelf(List<Book> books) {
this.books = books;
}
public List<Book> getBooks() {
return books;
}
}
/**
* 图书馆
*/
public class Library {
/**
* 查找图书作者
* @param shelf
* @param title
* @return
*/
public String findBookAuthor(Shelf shelf, String title) {
for (Book book : shelf.getBooks()) {
if (book.getTitle().equals(title)) {
return book.getAuthor();
}
}
return null;
}
}
在这个例子中,Library
类通过Shelf
类来获取Book
类的author
,这违反了迪米特法则,因为Library
类不应该知道Shelf
类的内部结构(这里指books
对象,并需要知道Book
的属性)。
解决
为了遵守迪米特法则,我们给Shelf
类添加查找图书作者的方法。
/**
* 书架
*/
public class Shelf {
private List<Book> books;
public Shelf(List<Book> books) {
this.books = books;
}
public List<Book> getBooks() {
return books;
}
/**
* 查找图书作者
* @param title
* @return
*/
public String findBookAuthor(String title) {
for (Book book : books) {
if (book.getTitle().equals(title)) {
return book.getAuthor();
}
}
return null;
}
}
/**
* 图书馆
*/
public class Library {
/**
* 查找图书作者
* @param shelf
* @param title
* @return
*/
public String findBookAuthor(Shelf shelf, String title) {
return shelf.findBookAuthor(title);
}
}
这样,Library
类直接从Shelf
获取图书作者,从而遵守了迪米特法则。
结语
迪米特法则是一种重要的设计原则,它指导我们如何设计模块间的交互,以减少耦合度,提升系统的可维护性和可扩展性。通过遵循这一原则,我们可以构建出更加灵活、易于管理的软件系统。希望今天的培训能够帮助大家更好地理解和应用迪米特法则。谢谢大家!