依赖反转是SOLID设计原则中的最后一个原理,Dependency Inversion。其核心的目的是减少模块与模块之间的耦合,提高代码的可维护性和扩展性。

依赖反转的关键点:

  1. 模块之前不应该存在直接的依赖关系,两者都应该依赖于抽象类或者接口
  2. 抽象不应该依赖于细节,细节需要依赖于抽象

下面以Node.js来举例,假设有一个UserSerivce类,需要从数据库中来查询用户信息,如果没有应用依赖反转,那么UserSerivce类需要依赖于数据库,这样会导致UserSerivce类与数据库耦合,如果数据库发生变化,那么UserSerivce类也需要跟着变化,这显然是不合理的。

class UserService {
  constructor(db) {
    this.db = db;
  }
  getUser(id) {
    return this.db.getUser(id);
  }
}

下面利用依赖反转来重构以上代码:

// IUserRepository.ts
 
abstract class IUserRepository {
  getUser(id) {
    throw new Error('not implemented');
  }
}
 
// UserRepository.ts
class UserRepository extends IUserRepository {
  constructor(db) {
    super();
    this.db = db;
  }
  getUser(id) {
    return this.db.getUser(id);
  }
}
 
// UserSerivce.ts
class UserSerivce {
  constructor(userRepository) {
    this.userRepository = userRepository;
  }
  getUserInfo(id) {
    return this.userRepository.getUser(id);
  }
}
 
//app.ts
const Db = require('./db');
const UserRepository = require('./UserRepository');
const UserService = require('./UserService');
const db = new Db()
const userRepository = new UserRepository(db);
const userService = new UserService(userRepository);
 
userService.getUserInfo(1);

通过这种依赖反转的方式,如果我们需要增加缓存或者是更换数据库技术,那么只需要重新实现一个IUserRepostory即可,UserServicelei本身不需要与存储细节耦合。