全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-16 10 分钟 ✍️ juanwangdev

依赖注入与控制反转

依赖注入与控制反转是构建松耦合系统的核心设计思想,广泛用于复杂前端架构。

核心概念

控制反转(IoC)

控制权从程序内部转移到外部容器,对象不再自行创建依赖,而是由外部提供。

依赖注入(DI)

IoC的具体实现方式,依赖对象通过构造函数、属性或接口从外部注入。

JavaScript
传统方式:对象内部创建依赖
IoC方式:外部容器注入依赖

实现方式

构造函数注入

JavaScript
// 不使用DI:紧耦合
class UserService {
  constructor() {
    this.db = new MySQLDatabase(); // 直接创建依赖
    this.logger = new ConsoleLogger();
  }
}

// 使用DI:松耦合
class UserService {
  constructor(db, logger) {
    this.db = db;        // 依赖从外部注入
    this.logger = logger;
  }
}

// 注入依赖
const db = new MySQLDatabase();
const logger = new ConsoleLogger();
const userService = new UserService(db, logger);

工厂注入

JavaScript
class ServiceFactory {
  constructor() {
    this.db = null;
    this.logger = null;
  }

  setDatabase(db) {
    this.db = db;
  }

  createUserService() {
    return new UserService(this.db, this.logger);
  }
}

容器注入

JavaScript
// 简易IoC容器
class Container {
  constructor() {
    this.services = new Map();
    this.instances = new Map();
  }

  // 注册服务
  register(name, factory, dependencies = []) {
    this.services.set(name, { factory, dependencies });
  }

  // 解析服务
  resolve(name) {
    if (this.instances.has(name)) {
      return this.instances.get(name);
    }

    const service = this.services.get(name);
    if (!service) {
      throw new Error(`Service ${name} not found`);
    }

    const deps = service.dependencies.map(dep => this.resolve(dep));
    const instance = service.factory(...deps);
    this.instances.set(name, instance);
    return instance;
  }
}

// 使用容器
const container = new Container();

container.register('db', () => new MySQLDatabase());
container.register('logger', () => new ConsoleLogger());
container.register('userService', (db, logger) => new UserService(db, logger), ['db', 'logger']);

const userService = container.resolve('userService');

实际应用

与测试结合

JavaScript
// 生产环境
const realDb = new MySQLDatabase();
const realLogger = new ConsoleLogger();
const userService = new UserService(realDb, realLogger);

// 测试环境:轻松替换依赖
const mockDb = { find: jest.fn(), save: jest.fn() };
const mockLogger = { log: jest.fn() };
const testUserService = new UserService(mockDb, mockLogger);

前端框架中的DI

JavaScript
// Angular风格
@Injectable({ providedIn: 'root' })
class AuthService {
  constructor(private http: HttpClient, private storage: StorageService) {}
}

// Vue/React中手动DI
class App {
  constructor() {
    const api = new ApiService();
    const store = new Store();
    this.authService = new AuthService(api, store);
  }
}

IoC与DI的关系

概念说明角色
IoC设计原则控制权的转移
DI实现模式IoC的具体实现
IoC容器工具框架管理依赖注入

DI是IoC的一种实现方式,IoC还可以通过服务定位器、模板方法等模式实现。

最佳实践

text
// 1. 面向接口编程
class UserService {
  constructor(database) { // 依赖抽象,非具体实现
    this.database = database;
  }
}

// 2. 使用依赖标记
const DEPENDENCIES = {
  DATABASE: 'Database',
  LOGGER: 'Logger',
  CACHE: 'Cache'
};

// 3. 生命周期管理
class Container {
  registerSingleton(name, factory) { /* 单例 */ }
  registerTransient(name, factory) { /* 每次新建 */ }
  registerScoped(name, factory) { /* 作用域内单例 */ }
}

要点总结

  1. IoC是原则:控制权从内部转移到外部
  2. DI是实现:通过构造函数、属性、接口注入依赖
  3. 核心价值:松耦合、易测试、易维护
  4. 容器作用:集中管理服务注册与依赖解析
  5. 测试友好:轻松注入Mock对象进行单元测试

存放路径:articles/JS/专家/设计模式与架构思想/依赖注入与控制反转.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 代理模式与装饰器模式
下一篇 → 单向数据流与状态管理
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库