对于依赖注入的思考

246 天前
 llej

突然想明白了为什么要有依赖注入了:这里只讨论在组合优于继承的这种情况下 一定会有许多的函数组合情况,而且还会有函数组合的组合,这样实质上形成了一个函数之间的依赖链路。

如果是直接在代码中硬编码对应的函数组合的话,我要实现一个新的高阶组合他和原来的高阶组合的唯一区别只是一个基础函数的实现不一致,那我基本需要重新复制一遍原来的组合代码,然后修改其中一个调用

如果要想复用原来的高阶组合,而只是修改其中对于该基础函数的替换的话,要么将该函数作为参数传递(这个传递链路可能很长),而依赖注入就是为了解决这个问题而存在的。

有了依赖注入,只需要在编写代码的时候就通过依赖注入来调用函数,后续的替换就十分的方便了。

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 的原型链就可以认为是一种依赖注入

只要实现 injectprovide 这两个函数就可以了

provide 实现 :接受一个 key 和 value , 将这两个参数和当前节点相绑定

inject 实现 :接受一个 key , 在任意一个节点,沿父级一直向上通过 key 查询对应的注入的值,找到了就返回,没有就找父级的父级。

inject 的实现基本和 js 对象基于原型链查找属性值的实现方式是一样的。所以我说 <u>js 的原型链就可以认为是一种依赖注入</u>

如何使用链表来理解呢:

比如 vue 中的依赖注入系统,这里的链表是组件树中,将组件理解为节点,然后一直查找上一层组件,一直到顶层,其中经过的所有节点就是一个链表,基于这个链表,最末端的节点,可以获取他的任意一个父级节点 provide 的值,并且在 key 相同的情况下 inject 的是离他最近的一个节点 provide 的值

但如果我们要以函数为节点,以函数调用栈作为链表来实现一个依赖注入系统可行吗?

答案是可以但又不可以,因为在浏览器中是受限的,只能基于 zone.js 来实现(存在缺陷)

在 node.js 的环境下可以选择使用 Async hooks 来达成同样的目的

3444 次点击
所在节点    程序员
21 条回复
zhuangzhuang1988
233 天前
@runlongyao2 真复杂的项目还是要的 比如说 vscode
https://github.com/microsoft/vscode/tree/main/src/vs/platform/instantiation/common
这是 vscode 的 IOC 实现,整个 vscode 都依赖
https://github.com/microsoft/vscode/blob/main/src/vs/workbench/browser/web.main.ts#L271 各种服务注册

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1106467

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX