为什么有 InversifyJS
有很多好的原因,但是我们想强调其中这些:
1. 真正解耦
InversifyJS 赋予你真正解耦的能力。考虑如下的类:
let TYPES = {
Ninja: Symbol.for("Ninja"),
Katana: Symbol.for("Katana"),
Shuriken: Symbol.for("Shuriken")
};
export { TYPES };
import { TYPES } from "./constants/types";
@injectable()
class Ninja implements Ninja {
private _katana: Katana;
private _shuriken: Shuriken;
public constructor(
@inject(TYPES.Katana) katana: Katana,
@inject(TYPES.Shuriken) shuriken: Shuriken
) {
this._katana = katana;
this._shuriken = shuriken;
}
public fight() { return this._katana.hit(); };
public sneak() { return this._shuriken.throw(); };
}
Ninja
类永远不会指向 Katana
或者 Shuriken
类。但是,它会指向接口(在设计时)或者符号(在运行时),由于这是抽象的所以这是可接受的。毕竟依赖抽象正是依赖反转所要做的。
InversifyJS 容器是应用中唯一清楚生命周期和依赖关系的元素。我们推荐在一个保存在包含应用源代码的根文件夹下名为 inversify.config.ts
的文件中按照如下方式来写:
import { TYPES } from "./constants/types";
import { Katana } from "./entitites/katana";
import { Shuriken } from "./entitites/shuriken";
import { Ninja } from "./entitites/ninja";
container.bind<Katana>(TYPES.KATANA).to(Katana);
container.bind<Shuriken>(TYPES.SHURIKEN).to(Shuriken);
container.bind<Ninja>(TYPES.NINJA).to(Ninja);
这意味着应用中所有的耦合关系发生在唯一一处:inversify.config.ts
文件中。
这非常重要,并且我们会用一个实例来证明其重要性。
让我们想象我们正在更改一个游戏的难度级别。
我们只需要去 inversify.config.ts
文件中并且修改 Katana 的绑定即可:
import { Katana } from "./entitites/SharpKatana";
if(difficulty === "hard") {
container.bind<Katana>(TYPES.KATANA).to(SharpKatana);
} else {
container.bind<Katana>(TYPES.KATANA).to(Katana);
}
你根本不需要修改 Ninja 文件!
需要付出的代价是符号或者字符串字面量的使用,但是只要你在一个文件中定义所有的字符串字面量,那么这个代价将有所缓和 (Redux 中的 actions 就是这么做的)。 好消息是未来这些符号或者字符串字面量 能够由 TS 编译器自动生成,但是目前这还在 TC39 委员会的手中。
2. 消除竞争问题
一些“老”的 JavaScript IOC 容器比如 angular 1.x 中的 $injector
会有些问题:
InversifyJS 消除了这些问题:
- 为短暂和单例生命周期提供支持。
- 由于标签、命名和上下文绑定,没有命名空间冲突。
- 这是一个独立库。
3. 拥有你能需要的所有特性
据我所知这是 JavaScript 中唯一拥有复杂依赖关系解决功能、多生命周期(短暂的、单例)以及很多其他功能的 IoC 容器(比如上下文绑定)。 在这之上还有增加特性的空间,比如拦截器或者 web worker 生命周期。 我们还有计划开发开发者工具,比如浏览器扩展以及中间件(日志、缓存……)。
4. 对象组合是一个痛点
你也许认为你不需要 IoC 容器。
如果之前的争论 还不够,那么你可能需要读一读下面的文章:
5. 类型安全
该库使用 TypeScript 开发所以如果你使用 TypeScript 那么天然类型安全,不过值得一提的是如果你尝试将 Katana 注入到一个期待 Shuriken
实现的类中,你会得到一个编译错误。
6. 棒极了的开发体验
我们非常努力地为你的 JavaScript 应用提供一个棒极了的 IoC 容器,同时也为你提供一个棒极了的开发体验。 我们话费了很多时间尝试让 InversifyJS 尽可能对用户友好,以及正在开发相关 Chrome 工具,而且已经开发了日志中间件来帮你在 Node.js 中调试。