架构整洁之道-08 设计原则-依赖倒置原则DIP

404 阅读2分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

依赖倒置

依赖倒置 Dependence Inversion Principle DIP.

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

依赖倒置原则的定义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

其核心思想是:要面向接口编程,不要面向实现编程。

实现方法

依赖倒置的目的是通过面向接口的编程来降低类间的耦合性,所以稳定的软件架构设计应该避免依赖易变的具体类,每个类都尽量使用接口或抽象类,任何类都不从具体类派生。

如何正确使用:

  • 不引用易变的具体实现类。无论静态语言还是动态语言都引用抽象接口类,对对象的创建增加约束,比如使用抽象工厂模式创建对象。
  • 不从易变的具体类实现派生
  • 不覆盖具体实现的方法。当依赖某对象时,对于父类的具体方法都进行覆盖重写
  • 不提任何具体实现和易变类的名字

以下Demo主要通过构造函数方式实现依赖倒置:

class Customer {
    constructor(
        private readonly shop: Shopping
        ){}
        
    async goShop() {
        return console.log(this.shop.sell());
    }
}
​
class Shopping {
    sell(){
     return '小卖部卖东西...';  
    }
}
​
(()=>{
    const shop = new Shopping();
    const cust = new Customer(shop);
    cust.goShop();
})();

依赖倒置的优点

  • 可以降低类之间的耦合性
  • 提高系统的稳定性
  • 减少并行开发引发的风险
  • 提高代码的可读性和可维护性

开闭原则和依赖倒置原则区别

  • 开闭原则:开启扩展,关闭修改;
  • 依赖倒置:抽象不依赖具体,具体应依赖抽象
  • 都是对类/接口的设计

软件设计第一课中讲述:一个好的软件设计者和架构师应该努力去减少接口的易变形,应尝试对于实现类增加函数而不改变接口。这也是我们使用DIP的原因:依赖不变的抽象,扩展具体实现。

参考资料