IoC

前端趋势: https://www.zhihu.com/question/468249924/answer/196607436

直接学习 nest 的依赖注入

https://juejin.cn/post/6930898274639593480#heading-0

https://juejin.cn/post/7013173275526168589

https://www.zhihu.com/question/441680476

控制反转(IoC)和依赖注入(DI)

IoC 的全称为 Inversion of Control,意为 控制反转,它是 OOP 中的一种原则(虽然不在 n 大设计模式中,但实际上 IoC 也属于一种设计模式),它可以很好的解耦代码。

依赖注入优点

与手动 New 的区别

依赖关系树更加清晰

如果没有依赖倒置,我需要在每个调用了实例的方法,确认他到底用了哪些方法,我得把这些方法都实现了,才能替换。如果想节约时间,新类就得继承旧类,重写旧类的方法。这里继承就会导致新的耦合。会导致依赖树变得更加复杂,我依赖的是实例的父类,实际调用的是实例的子类。

如果有依赖倒置,我只需要确认接口上有哪些方法,实现接口上的方法即可,新类就可以替换旧类了。依赖树更加清晰,无论是调用旧类还是新类,面向的都是接口。旧类和新类之间没有关系

可以用不同的实例满足接口。比如人依赖交通工具上班,无论是公交、地铁、单车都可以满足接口。

如果没有依赖倒置的话,人必须依赖交通工具这个父类,然后用多态去支持,这样就产生了依赖树

强制依赖接口

强制让代码依赖接口和抽象,而不是直接依赖实现

依赖接口之后,即时没有真正的实现,用到的地方也不会报错。但是实例内部会提示没有实现

如果没有 IoC 容器,我们会直接调用这个实例上的方法,在运行时有这个实例方法就不会报错

如果有 IoC 容器,实际上是强制我们依赖了这个实例的接口,我们没有办法直接依赖实例的方法了,就是一种解耦. 如果实现没有满足接口在编译期就会报错了

不需要知道如何创建实例

调用实例时,不需要知道如何去创建这个实例。 这样减少了工作量,也减少了耦合。因为 new 一个实例,可能需要引入这个 class 依赖的多个其他 class,这些显然不是调用方需要去关心的

只要 IoC 容器知道就可以了, 默认了所有的依赖模块都是 DI 注入的

那 IOC 容器不就得同时依赖 A 和 B 吗?以后 A 有变化,需要改 IOC 容器,B 有变化也需要改 IOC 容器?

其实不是的, IoC 容器只是进行了实例化, 并没有依赖 A 和 B 的任何属性或者方法, 不论 A 和 B 怎么修改, 都不会影响实例化.

方便进行单元测试

适用场景

控制反转常用于经常要改来改去的依赖,如果不怎么会变动,就没必要硬塞一个控制反转

竞对

当然,可以用 static method 或者 singleton 去实现,然后在某个时刻时统一初始化。只是每多一个服务对象,就要去改初始化代码,面对复杂的依赖时,还要知道初始化顺序,实际上就是手动做一个 bean factory,只是耦合的更严重了。

IoC 实现

我们现在能够知道 IoC 容器大概的作用了:容器内部维护着一个对象池,管理着各个对象实例,当用户需要使用实例时,容器会自动将对象实例化交给用户。

DI

DI 的全称为 Dependency Injection,即 依赖注入。依赖注入是控制反转最常见的一种应用方式,就如它的名字一样,它的思路就是在对象创建时自动注入依赖对象。

DI 与装饰器

因为装饰器语法还不稳定, 没必要深究具体的实现. 把 swan 的那一套思路拿过来就可以了