ReactNative進階(三十一): IoC 框架 InversifyJS解讀
文章目錄
簡介
為什么要有 InversifyJS?
目標
安裝
應用示例
步驟 1: 聲明接口和類型
步驟 2: 使用 @injectable 和 @inject 裝飾器聲明依賴
步驟 3: 創建和配置容器
步驟 4: 解析依賴
拓展閱讀
簡介
InversifyJS ,一個強大又輕量的控制反轉容器,提供給JavaScript 和 Node.js 應用使用,使用TypeScript編寫。
InversifyJS 是一個輕量的 (4KB) 控制反轉容器 (IoC),可用于編寫 TypeScript 和 JavaScript 應用。 它使用類構造函數去定義和注入它的依賴。InversifyJS API 友好易懂, 鼓勵對 OOP 和 IoC 最佳實踐的應用.
為什么要有 InversifyJS?
JavaScript 現在支持面向對象編程,基于類的繼承。 這些特性不錯但事實上它們也是危險的。 我們需要一個優秀的面向對象設計(比如 SOLID),Composite Reuse等)來保護我們避免這些威脅。然而,面向對象的設計是復雜的,所以InversifyJS應運而生。
InversifyJS 是一個工具,它能幫助 JavaScript 開發者,寫出出色的面向對象設計的代碼。
目標
InversifyJS有4個主要目標:
允許JavaScript開發人員編寫遵循 SOLID 原則的代碼。
促進并鼓勵遵守最佳的面向對象編程(OOP)和依賴注入(IoC)實踐。
盡可能少的運行時開銷。
提供藝術編程體驗和生態。
安裝
可以使用npm獲得最新的版本和類型定義:
$ npm install inversify reflect-metadata --save
1
注:由于 InversifyJS 通過反射來獲取裝飾器的相關元數據,所以需要額外安裝庫
reflect-metadata。
Inversify npm 包已經包含了 InversifyJS 的類型定義
:警示: 重要! InversifyJS 需要 TypeScript 的版本 >= 2.0 還有
experimentalDecorators, emitDecoratorMetadata, types and lib 在 tsconfig.json 中 compilerOptions 的配置如下:
{ "compilerOptions": { "target": "es5", "lib": ["es6"], "types": ["reflect-metadata"], "module": "commonjs", "moduleResolution": "node", "experimentalDecorators": true, "emitDecoratorMetadata": true } }
1
2
3
4
5
6
7
8
9
10
11
inversifyjs需要現代JavaScript引擎,支持以下特性
Reflect metadata
Map
Promise (Only required if using provider injection)
Proxy (Only required if using activation handlers)
如果運行環境不支持這些特性,可能需要導入 shim 或 polyfill.
:警示: reflect-metadata polyfill 應該在您整個應用中只導入一次, 因為 Reflect 對象需要成為一個全局的單例。
應用示例
inversifyjs 基本用法和 API應用示例如下:
步驟 1: 聲明接口和類型
目標是編寫遵循依賴倒置原則的代碼。
這意味著我們應該 ”依賴于抽象而不依賴于具體實現“ 。
先聲明一些接口(抽象)。
// file interfaces.ts interface Warrior { fight(): string; sneak(): string; } interface Weapon { hit(): string; } interface ThrowableWeapon { throw(): string; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Inversifyjs 需要在運行時使用類型標記作為標識符。接下來將使用 Symbol 作為標識符,也可以使用類或字符串。
// file types.ts const TYPES = { Warrior: Symbol.for("Warrior"), Weapon: Symbol.for("Weapon"), ThrowableWeapon: Symbol.for("ThrowableWeapon") }; export { TYPES };
1
2
3
4
5
6
7
8
9
警示: 推薦使用 Symbol,但 InversifyJS 也支持使用類和字符串字面值。
步驟 2: 使用 @injectable 和 @inject 裝飾器聲明依賴
接下來,聲明一些類,實現剛剛聲明的接口。需要使用 @injectable 裝飾器去注解。
當一個類依賴于某個接口時,我們需要使用 @inject 裝飾器,來定義在運行時可用的接口標識。在這種情況下,將使用 Symbol, 如 Symbol.for("Weapon") 和 Symbol.for("ThrowableWeapon") 作為運行時的標識。
// file entities.ts import { injectable, inject } from "inversify"; import "reflect-metadata"; import { Weapon, ThrowableWeapon, Warrior } from "./interfaces" import { TYPES } from "./types"; @injectable() class Katana implements Weapon { public hit() { return "cut!"; } } @injectable() class Shuriken implements ThrowableWeapon { public throw() { return "hit!"; } } @injectable() class Ninja implements Warrior { private _katana: Weapon; private _shuriken: ThrowableWeapon; public constructor( @inject(TYPES.Weapon) katana: Weapon, @inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon ) { this._katana = katana; this._shuriken = shuriken; } public fight() { return this._katana.hit(); } public sneak() { return this._shuriken.throw(); } } export { Ninja, Katana, Shuriken };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
如果更喜歡使用屬性注入而不是構造函數注入,那就可以不用聲明類的構造函數了,屬性注入方式如下:
@injectable() class Ninja implements Warrior { @inject(TYPES.Weapon) private _katana: Weapon; @inject(TYPES.ThrowableWeapon) private _shuriken: ThrowableWeapon; public fight() { return this._katana.hit(); } public sneak() { return this._shuriken.throw(); } }
1
2
3
4
5
6
7
步驟 3: 創建和配置容器
推薦在命名為 inversify.config.ts 的文件中創建和配置容器。這是唯一有耦合的地方。 在項目其余部分中的類,不應該包含對其他類的引用。
// file inversify.config.ts import { Container } from "inversify"; import { TYPES } from "./types"; import { Warrior, Weapon, ThrowableWeapon } from "./interfaces"; import { Ninja, Katana, Shuriken } from "./entities"; const myContainer = new Container(); myContainer.bind
1
2
3
4
5
6
7
8
9
10
11
12
13
步驟 4: 解析依賴
可以使用方法 get
import { myContainer } from "./inversify.config"; import { TYPES } from "./types"; import { Warrior } from "./interfaces"; const ninja = myContainer.get
1
2
3
4
5
6
7
8
正如我們所看到的,Katana and Shuriken 被成功的解析和注入進 Ninja。
InversifyJS 支持 ES5 和 ES6 ,而且可以在沒有 TypeScript 環境下使用。
不做知識的搬運工,只做知識的匯聚者!
注:本文轉載于https://doc.inversify.cloud/zh_cn/,學習InversifyJS,看此文足矣??!墻裂推薦!!
拓展閱讀
InversifyJS【Github】
中文文檔
Java JavaScript
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。