传统方式
比如现在有三个类,其中B类和C类中需要用到A类的实例(也就是B类和C类依赖A类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class A { name:string constructor() { this.name = "yajue" } }
class B { a:any constructor() { this.a = new A().name } }
class C { a:any constructor() { this.a = new A().name } }
|
如果将A类改为
1 2 3 4 5 6
| class A { name:string constructor(name:string) { this.name = name } }
|
B类和C类内部就开始飘红了
说明这些类之间的耦合度较强(创建B类或C类时出现了A类本尊)
IOC方式
浅谈控制反转与依赖注入 - 知乎 (zhihu.com)
IOC
全称Inversion of Control,控制反转
- 高层模块不应该依赖低层模块,二者都应该依赖其抽象
- 抽象不应该依赖细节,细节应该依赖抽象
DI
Dependency Injection,依赖注入,其实和IOC就是一个东西
由于控制反转概念比较含糊,所以2004年大师级人物Martin Fowler又给出了一个新的名字“依赖注入”
可能IOC只容易被理解到容器控制对象这个层面,很难让人想到谁来维护对象关系
代码
Container用来收集并集中管理依赖,就是个IOC容器
当C类需要用到其他类时,构造器通过Container直接获取类的实例,就不用在C的内部创建实例了
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 42 43 44
| class A { name:string constructor(name:string) { this.name = name } }
class B { name:string constructor(name:string) { this.name = name } }
class Container { mod:any constructor() { this.mod = {} }
provide(key:string,mod:any) { this.mod[key] = mod }
get(key:string) { return this.mod[key] } }
const mod = new Container() mod.provide("a",new A("yjsp")) mod.provide("b",new B("yajue"))
class C { a:any b:any constructor(mod:Container) { this.a = mod.get("a") this.b = mod.get("b") } }
|
这使类们从复杂的关系中解耦,让程序可以单独拓展其他功能,也可以方便地加入其他模块,减少维护成本