Z

依赖倒置原则(Dependence Inversion Principle)

High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

依赖倒置原则有三点:

  • 高层模块不应该依赖底层模块,而是依赖其抽象
  • 抽象不应该依赖于细节
  • 细节应该依赖抽象

在业务逻辑中,拆的不能再拆的原子逻辑就是底层模块,高层模块是由一个个原子逻辑组合而成,而两者的的依赖应该依靠抽象,两者不直接发生关系。

 1class People {
 2    private phone: iPhone;
 3 
 4    buy(phone: iPhone) {
 5        this.phone = phone;
 6    }
 7 
 8    call() {
 9        this.phone.call();
10    }
11 
12    sale() {
13        const target = this.phone;
14        this.phone = null;
15        return target;
16    }
17}
18 
19class iPhone {
20    call() {
21    }
22}
23 
24const tom = new People();
25tom.buy(new iPhone());
26tom.call();
27tom.sale();

在上面的代码中,People直接依赖了iPhone这个实体,创建了一个实例tom,tom买了一部iPhone,打了通电话,然后把它卖了,目前看上去没什么问题,但如果将来有一天tom想买Nokia怎么办?难道把方法buy的参数和私有属性phone的类型改成? Nokia | iPhone?如果未来想买Sony再加个Sony?这显然是不合理的,那么最好的办法就是通过interface来连接两者的依赖关系。

 1class People {
 2    private phone: IMobilePhone;
 3 
 4    buy(phone: IMobilePhone) {
 5        this.phone = phone;
 6    }
 7 
 8    call() {
 9        this.phone.call();
10    }
11 
12    sale() {
13        const target = this.phone;
14        this.phone = null;
15        return target;
16    }
17}
18 
19interface IMobilePhone {
20    call: () => void
21}
22 
23class iPhone implements IMobilePhone {
24    call() {
25    }
26}
27 
28class Sony implements IMobilePhone {
29    call() {
30    }
31}
32 
33const tom = new People();
34tom.buy(new iPhone());
35tom.buy(new Sony());
36tom.call();
37tom.sale();

现在把People原本依赖的iPhone改成interface IMobilePhone,只要某个class实现了IMobilePhone,就能buy它,这样就拆开了高层模块与底层模块,代码的可维护性大大加强,这就是第一条的含义:高层模块不应该依赖底层模块,而是依赖其抽象。

后两条也很好理解,例如在ts中abstract class或interface应该作为实现类的抽象,也就是说一个实现类应该implements一个interface或者abstract class,而不是interface来implements一个class,而后者在ts语法中是合法的。对于实体间的依赖,我们都应该使用interface或者abstract class来声明。