查看回答
查看回答
​
​
​darukjs.com
​github.com
​
​

灵剑
灵剑2020-04-26

说实话我觉得Spring的IOC设计是因为Java的类不是真正的对象,所以需要用反射实现自动化;Javascript的class或者function都是可以赋值的对象,没必要Spring风格IOC的,搞个独立的文件管理别名就行了,比如从另外一个文件里面import进来换个名字再export出去,这样中转一下。

11 条回复
木香丘
木香丘 (作者) 回复灵剑2020-04-27
不认同,IoC 是控制反转,解耦了依赖关系,方便开发者面向抽象编程,解耦具体实现,对象托管到容器,容器可以为我们做更多的事,特别是在扩展性方面。

比如 Malagu 框架内部几乎所有实现都可以很方便地被替换掉,不需要侵入框架代码,这种无所不能的扩展能力就 IoC 带来的。

IoC 是一种编程思想。ts 也适用。

无论前端还是后端,社区上有越来越多支持 IoC 的ts 框架了
灵剑
灵剑回复木香丘 (作者) 2020-04-27

关键是没必要用Spring的方法实现

灵剑
灵剑回复木香丘 (作者) 2020-04-27

这么解释吧,IoC要解决的问题是一般创建一个对象的时候需要new <MyClass>,这里需要在代码里写死这个MyClass,而不能指定接口,因而这个代码不能灵活修改MyClass的实现。问题是这个其实只有Java是这样的,在JavaScript中,function和class都是对象,既可以作为参数传入,也可以另起一个变量名保存在别处,还可以变成object的属性或者数组的元素,这样其实不需要特别的设计,只需要把接口到类的映射变成一种配置,然后查找配置找到类就可以了。不需要特别重量级的IoC支持。

木香丘
木香丘 (作者) 回复灵剑2020-04-27
用户体验设计和 Spring 很像,一是我写了很多年的 java ,有先入为主因素吧,另外,Spring IoC 的用户体验发自内心认为是最好的,主观判断,不喜勿喷哈
灵剑
灵剑回复木香丘 (作者) 2020-04-27

就是说完全可以用一个泛用的配置系统来代替整套IoC,其实会更清晰一些。举个例子,假定配置系统有一个接口getConfig(key),可以返回对应的配置项,可能是个对象(包括function或class),那么其实就可以这么写:


let MyInterfaceImpl = getConfig("MyInterface");

let MyInterfaceImpl2 = getConfig("MyInterface2");


function someInterface(){

...

let newObj = new MyInterfaceImpl(para1, para2);

let depend = getSingleton(MyInterfaceImpl2);

};


这里第一个地方看上去就是普通的new,但因为这里的MyInterfaceImpl是从配置系统当中加载的,所以实际上就起到了依赖注入的作用;第二个调用一个通用方法实现Singleton,原理其实就是有个全局的Map,检测这个Map是否已经有某个key,如果没有就new一个新的设置上去而已。其实要比Java简洁也通用得多。

木香丘
木香丘 (作者) 回复灵剑2020-04-27
如果是 js,我也认同 IoC 作用没那么大,如果是 ts 那就不一样了,ts 有接口,很多面向对象编程原则才能施展。ts 有了装饰器,才能让 IoC 如虎添翼。

js 对像是很灵活,假如我们认可面向抽象编程,那么我就应该避免动态修改对象。

做一个轻量级的 IoC 没问题,malagu 底层使用 in versifyjs 这个开源的 IoC,也是很轻量级的。IoC 有很多标配的东西,比如依赖注入、单例、原型等等,这些特性注定就不会简单。
木香丘
木香丘 (作者) 回复灵剑2020-04-27
考虑单例情况:
a 对象依赖 b 对象,b 对象依赖 c,c 对象又依赖 d 对象,你怎么如何创建 a 对象?

如果硬编码,还能写出来,封装成通用逻辑,就会变得复杂,就是一个依赖图了,因为可能有循环依赖了。

假如这个你也实现了,如何实现通过 lazy 初始化对象,去优化内存以及执行效率。也就是说,一个对象只有用到了才会被初始化(单列情况哈)。

复杂度有上升一个层次。

绝对不是一个简单 map 的问题。
灵剑
灵剑回复木香丘 (作者) 2020-04-27

就直接new getConfig("a")就好了啊……你说的那些别的依赖本来就应该是在那些类的构造函数当中定义的,对外又不可见。按我前面写的那个方式本来也就是第一次用到的时候才初始化的单例对象。

灵剑
灵剑回复木香丘 (作者) 2020-04-27

如果是Singleton的依赖也是一样的,只需要在创建Singleton的时候往Map里设一个表示“正在创建”的临时对象,然后查找Singleton的时候发现设了这个,自然就发现循环依赖了。再设计得巧妙一些还可以直接在编译器就发现这样的循环依赖(不过跟Lazy初始化可能是矛盾的,因为Lazy的情况下有可能不触发循环依赖)

Ryou ikonn
Ryou ikonn回复木香丘 (作者) 2020-09-04

我觉得灵剑说的很对啊。首先为什么你会有abcd对象相互依赖的场景,很多东西抽象出来配置化 不是一样的吗。单例什么的 直接装饰器就可以 跟ioc没什么关系 使用起来很方便。

木香丘
木香丘 (作者) 回复Ryou ikonn2020-09-04
对于一个真实应用,对象之间的依赖关系必然会比你想象中要复杂得多,另外面向对象程序编程本来也推荐多用组合少用继承,IoC 不是简单的单例,这是一种思想,把对对象的管理托管给容器,这里面好处很多,依赖倒置、aop、ioc、依赖注入、lazy 等等,我不想过多讨论 ioc 存在的价值,你可以去网上了解一下 ioc 历史背景,解决什么问题。