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 的那一套思路拿过来就可以了