依赖倒置原则 (Dependency Inversion Principle, DIP)

DIP 是五大 SOLID 原则中的重要组成部分。它们的目标是通过合理的设计和架构,提升系统的可维护性、扩展性和灵活性。


定义

依赖倒置原则的核心思想是:高层模块不应该依赖低层模块,二者都应该依赖于抽象

也就是说,具体的实现类应该依赖于接口或抽象类,而不是高层模块直接依赖实现细节。

依赖倒置原则常常用于创建解耦的系统,减少代码模块之间的直接依赖性。

主要内容

  • 高层模块(如业务逻辑层)不应该依赖低层模块(如数据访问层),二者应该依赖于接口或抽象类。
  • 抽象不应该依赖具体实现,而具体实现应该依赖于抽象

好处

  • 增强灵活性:代码依赖于接口或抽象类,便于更换不同的实现,而不需要修改高层模块的代码。
  • 解耦模块:高层模块和低层模块通过抽象层进行交互,降低了耦合度,便于维护和扩展。
  • 可扩展性强:添加新的实现类时,不需要改变原有的高层模块,只需实现接口或继承抽象类即可。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 抽象层
interface NotificationService {
void sendNotification(String message);
}

// 低层模块实现
class EmailNotificationService implements NotificationService {
@Override
public void sendNotification(String message) {
System.out.println("Sending email: " + message);
}
}

// 高层模块
class UserController {
private NotificationService notificationService;

public UserController(NotificationService notificationService) {
this.notificationService = notificationService;
}

public void notifyUser(String message) {
notificationService.sendNotification(message);
}
}

// Main方法
public class Main {
public static void main(String[] args) {
// 依赖于接口,而不是具体实现
NotificationService notificationService = new EmailNotificationService();
UserController userController = new UserController(notificationService);
userController.notifyUser("Welcome to the system!");
}
}

在这个例子中,UserController 类不直接依赖于具体的 EmailNotificationService,而是依赖于抽象的 NotificationService 接口。

通过这种方式,可以轻松替换 NotificationService 的实现类(例如可以换成 SMSNotificationService),而无需修改 UserController 的代码。

总结

DIP 的关键在于高层模块与低层模块的解耦,通过接口或抽象类将二者连接起来,避免高层模块直接依赖低层模块的实现细节,使系统具有更高的灵活性和可维护性。