控制反转
控制反转
控制反转(Inversion of Control, IoC) 是一种软件设计原则,它通过将对象的控制权从类自身转移到外部容器或框架中,从而减少了类与类之间的耦合关系,提高了灵活性和可扩展性。
在传统的面向对象编程中,类负责创建它所依赖的对象和管理自己的依赖。然而,控制反转改变了这种情况,它让外部容器或框架负责创建和管理这些依赖对象,而不是让类自己去创建。简单来说,控制反转就是将控制权类本身转移到外部容器,让容器来决定什么时候、如何创建对象以及如何注入它们的依赖。
依赖注入优势
依赖注入是控制反转的一种实现方式。通过依赖注入,外部容器负责将依赖对象注入到类中,而不是类自己去创建这些依赖。
- 硬编码方式
ts
// EmailService.ts
class EmailService {
send(to: string, message: string) {
console.log(`发送邮件给 ${to}: ${message}`);
}
}ts
// UserService.ts
import { EmailService } from './EmailService';
class UserService {
private emailService: EmailService;
constructor() {
// ❌ 缺点:UserService 主动创建了 EmailService 实例
// 如果以后想换成 SMS 模块,或者想在测试时不发真实邮件,就得改代码
this.emailService = new EmailService();
}
register(email: string) {
console.log('用户注册成功');
this.emailService.send(email, '欢迎加入!');
}
}- 使用依赖注入:
js
// 定义一个接口(TS 的灵魂所在)
interface NotificationService {
send(to: string, message: string): void;
}
// 邮件实现
class EmailService implements NotificationService {
send(to: string, message: string) { console.log(`邮件通知: ${to}`); }
}
// 短信实现
class SmsService implements NotificationService {
send(to: string, message: string) { console.log(`短信通知: ${to}`); }
}
// UserService 变被动了
class UserService {
// ✅ 优点:UserService 不关心具体是谁发,只要符合接口就行
constructor(private readonly notifier: NotificationService) {}
register(email: string) {
this.notifier.send(email, '欢迎!');
}
}
// --- 在应用入口处执行“注入” ---
const emailSvc = new EmailService();
const userSvc = new UserService(emailSvc); // 注入 Email 服务
userSvc.register('test@example.com');依赖注入类型
构造器注入
通过构造函数将依赖项传递给对象
js
class Car {
private engine: Engine;
constructor(engine: Engine) {
this.engine = engine; // engine是外部传入的依赖
}
start() {
this.engine.run();
}
}属性注入
通过公开的属性将依赖项注入到对象中
js
class Car {
engine: Engine;
setEngine(engine: Engine) {
this.engine = engine; // engine是外部传入的依赖
}
start() {
this.engine.run();
}
}方法注入
依赖通过方法传入。
js
class Car {
start(engine: Engine) {
engine.run(); // engine是通过方法传入的依赖
}
}