首页

对于依赖注入的思考

Suddenly Realized Why Dependency Injection Is Necessary
note​ 突然想明白了为什么要有依赖注入了:这里只讨论在组合优于继承的这种情况下 一定会有许多的函数组合情况,而且还会有函数组合的组合,这样实质上形成了一个函数之间的依赖链路。
如果是直接在代码中硬编码对应的函数组合的话,我要实现一个新的高阶组合他和原来的高阶组合的唯一区别只是一个基础函数的实现不一致,那我基本需要重新复制一遍原来的组合代码,然后修改其中一个调用
如果要想复用原来的高阶组合,而只是修改其中对于该基础函数的替换的话,要么将该函数作为参数传递(这个传递链路可能很长),而依赖注入就是为了解决这个问题而存在的。
有了依赖注入,只需要在编写代码的时候就通过依赖注入来调用函数,后续的替换就十分的方便了。
js
function baseFn_A(){} function baseFn_B(){} function higherFn_B(){ baseFn_A() //other baseFn ... } function higherFn_C(){ higherFn_B() //other baseFn / higherFn ... } // 这中间还可能有更多层次的这样的套娃 // 上面存在一个依赖链路 higherFn_C>higherFn_B>baseFn_A // 如果我要实现一个新的函数 higherFn_C2 ,它和 higherFn_C 唯一的区别就是调用的是 baseFn_B 而非 baseFn_A // 我认为依赖注入就是为了更方便的创建 higherFn_C2 而不需要改动特别多的代码

如何实现依赖注入

依赖注入可以使用链表来理解。js 的原型链就可以认为是一种依赖注入
只要实现 inject​ 和 provide​ 这两个函数就可以了
provide​ 实现 :接受一个 key 和 value , 将这两个参数和当前节点相绑定
inject​ 实现 :接受一个 key, 在任意一个节点,沿父级一直向上通过 key 查询对应的注入的值,找到了就返回,没有就找父级的父级。
inject​ 的实现基本和 js 对象基于原型链查找属性值的实现方式是一样的。所以我说 js 的原型链就可以认为是一种依赖注入
如何使用链表来理解呢:
比如 vue 中的依赖注入系统(树形结构依赖注入),这里的链表是组件树中,将组件理解为节点,然后一直查找上一层组件,一直到顶层,其中经过的所有节点就是一个链表,基于这个链表,最末端的节点,可以获取他的任意一个父级节点 provide​ 的值,并且在 key 相同的情况下 inject ​的是离他最近的一个节点 provide ​的值
但如果我们要以函数为节点,以函数调用栈作为链表来实现一个依赖注入系统可行吗?
答案是可以但又不可以,因为在浏览器中是受限的,只能基于 zone.js 来实现(存在缺陷)
在 node.js 的环境下可以选择使用 Async hooks 来达成同样的目的

相关领域知识

依赖注入是实现依赖倒置的一种办法

传递依赖一般有

通过方法注入 参数逐层传递
通过上下文注入 需要全局管理依赖生命周期,比如大型应用中多个模块需要共享依赖。

实现依赖注入所需要依赖的数据结构一般有

树形结构依赖注入
依赖形成层次化、父子关系明确。
应用场景:UI 组件嵌套(React/Vue)、层次化配置等。
线性依赖注入
依赖按顺序逐一注入,无复杂层次关系。
应用场景:函数调用链。
图结构依赖注入
依赖之间可能存在复杂交互或循环引用。
应用场景:任务调度、资源共享系统。
无依赖注入 (Dependency-Free)
依赖全部内置或硬编码,常见于简单脚本或微服务。