ioc是什么意思怎么用(控制反转IOC是什么?)

时间:2024-07-08 09:30:27 浏览:100


IOC,全称为 Inversion Of Control,即 控制反转

控制反转是面向对象编程中的一种设计原则,作用是降低各个模块之间的耦合度。

控制反转是思想,不是具体实现。

为什么需要控制反转?

假如 Class A 需要依赖 Class B,我们一般在 A 的构造函数中实例化 B,像这样:

class A {
  constructor() {
    this.b = new B();
  }
  // ...
}

这导致了耦合,A 对 B 的依赖,是写在 A 的实现中的。如果你要把 B 换成一个加强版的 BPlus,你就要改 A 的实现。

这时候,我们可以用控制反转。

“控制反转” 这个词怎么理解?就是将原本需要程序员手动控制的程序流程,改成通过框架来控制,从原来的程序员手工控制,改为框架控制

依赖注入(DI)

DI,英文全称 Dependency Injection,即依赖注入。

依赖注入是控制反转的一种常见实现。

依赖注入这词听起来高大上,很有噱头,实际上实现非常简单,就是将依赖的 Class 先在外面实例化好,再注入到需要它的 Class 中。

像前面的 A 和 B 的依赖关系,我们可以改成:

class A {
  constructor(b) {
    this.b = b;
  }
  // ...
}
const b = new B(); // 在外部实例化 B
const a = new A(b); // 依赖注入

上面是通过构造函数来注入实例对象。我们也可以额外写一个 setB 方法来注入:

class A {
  constructor() {}
  setB(b) {
    this.b = b;
  }
  // ...
}
const b = new B(); // 在外部实例化 B
const a = new A(); 
a.setB(b); // 依赖注入

使用了依赖注入的技巧后,A 和 B 就解耦了,B 就可以很方便地做替换,如:

const bPlus = new BPlus(); // 在外部实例化 B
const a = new A(bPlus); // 依赖注入

Nestjs 的 IOC

如果你用一些框架,它们可以把依赖注入过程做得更优雅,比如 Nestjs。

import { UserService } from './user.service';
@Controller('user')
export class UserController {
  // 通过类型,判断要进行注入哪个类
  constructor(private readonly userService: UserService) {}
  
  @Get()
  findAll() {
    // 这里我们用到了 this.userService
    // 我们代码里没写注入逻辑,但 Nestjs 帮我们注入了
    return this.userService.findAll();
  }
}

在 Nestjs 的 Controller 类中,我们只要在构造函数中声明该类,Nestjs 就能自动扫描注册的依赖列表,从中找出正确的类,并帮你实例化并注入,完全不需要你手动操作。

Nestjs 能做到这点,是利用了 TypeScript 的装饰器和 Reflect.metadata 的能力。