你有没有遇到过这样的情况:改一个功能,结果好几个地方都得跟着改?就像修个水龙头,结果发现水管、阀门、热水器都连在一起,动哪都不省心。在写代码时,这种“牵一发而动全身”的问题很常见,而“依赖注入”就是来解决这个问题的。
什么是依赖注入?
说白了,依赖注入就是把一个类需要的“工具”从外面给它,而不是让它自己去创建。就像做饭时,你不该自己去种菜、养猪,而是直接从市场买好食材下锅。
举个简单的例子。假设我们有一个发送通知的功能,可以发邮件或者发短信。
不使用依赖注入的做法:
class NotificationService {
public void send(String message) {
EmailSender emailSender = new EmailSender();
emailSender.send(message);
}
}
这样写的问题是:如果以后想改成发短信,就得改这个类。而且测试的时候也没法轻易换成假的发送器。
用依赖注入改造一下
先把发送方式抽象成接口:
interface MessageSender {
void send(String message);
}
class EmailSender implements MessageSender {
public void send(String message) {
// 发送邮件逻辑
System.out.println("邮件已发送:" + message);
}
}
class SMSSender implements MessageSender {
public void send(String message) {
// 发送短信逻辑
System.out.println("短信已发送:" + message);
}
}
然后让通知服务接收一个发送器,而不是自己创建:
class NotificationService {
private MessageSender sender;
// 构造函数注入
public NotificationService(MessageSender sender) {
this.sender = sender;
}
public void send(String message) {
sender.send(message);
}
}
使用的时候,你想用哪个就传哪个:
MessageSender email = new EmailSender();
NotificationService service = new NotificationService(email);
service.send("你好,这是一条测试消息");
如果想发短信,只需要换一个参数:
MessageSender sms = new SMSSender();
NotificationService service = new NotificationService(sms);
service.send("你好,这是一条测试消息");
你看,核心逻辑没变,但灵活性大大提升。加新方式也不用动老代码,符合“开闭原则”。
这种写法在 Spring 这类框架里很常见。你写的类只要声明“我需要什么”,框架就会自动把合适的对象塞进来,不用你操心。
刚开始可能觉得多此一举,但项目一大,你会发现这种结构清晰多了。改功能不慌,测代码也方便。