什么是依赖倒置原则?为什么它很重要?


当前回答

当我们设计软件应用程序时,我们可以考虑低层类——实现基本和主要操作的类(磁盘访问、网络协议……)和高层类——封装复杂逻辑的类(业务流……)。

最后一个依赖于低级类。实现这种结构的自然方法是编写低级类,一旦我们有了它们,就编写复杂的高级类。由于高级类是根据其他类定义的,这似乎是一种合乎逻辑的方法。但这不是一个灵活的设计。如果我们需要替换一个低级类,会发生什么?

依赖倒置原则指出:

高级模块不应该依赖于低级模块。两者都应该依赖于抽象。 抽象不应该依赖于细节。细节应该依赖于抽象。

这个原则试图“颠倒”传统的概念,即软件中的高级模块应该依赖于低级模块。在这里,高级模块拥有由低级模块实现的抽象(例如,决定接口的方法)。因此,较低级别的模块依赖于较高级别的模块。

其他回答

依赖倒置原理(DIP)

它是SOLID[About]的一部分,SOLID[About]是OOD的一部分,由Bob叔叔介绍。它是关于类(层…)之间的松散耦合。类不应该依赖于具体的实现,类应该依赖于抽象/接口

问题:

//A -> B
class A {
  B b

  func foo() {
     b = B();
  }
}

解决方案:

//A -> IB <|- B
//client[A -> IB] <|- B is the Inversion 
class A {
  IB ib // An abstraction between High level module A and low level module B

  func foo() {
     ib = B()
  }
}

现在A不依赖于B(一对一),现在A依赖于B实现的接口IB,这意味着A依赖于IB的多重实现(一对多)

[DIP vs DI vs IoC]

当我们设计软件应用程序时,我们可以考虑低层类——实现基本和主要操作的类(磁盘访问、网络协议……)和高层类——封装复杂逻辑的类(业务流……)。

最后一个依赖于低级类。实现这种结构的自然方法是编写低级类,一旦我们有了它们,就编写复杂的高级类。由于高级类是根据其他类定义的,这似乎是一种合乎逻辑的方法。但这不是一个灵活的设计。如果我们需要替换一个低级类,会发生什么?

依赖倒置原则指出:

高级模块不应该依赖于低级模块。两者都应该依赖于抽象。 抽象不应该依赖于细节。细节应该依赖于抽象。

这个原则试图“颠倒”传统的概念,即软件中的高级模块应该依赖于低级模块。在这里,高级模块拥有由低级模块实现的抽象(例如,决定接口的方法)。因此,较低级别的模块依赖于较高级别的模块。

查看这个文档:依赖倒置原则。

它基本上是说:

高级模块不应该依赖于低级模块。两者都应该依赖于抽象。 抽象永远不应该依赖于细节。细节应该依赖于抽象。

至于为什么它很重要,简而言之:更改是有风险的,通过依赖于概念而不是实现,您减少了在调用站点更改的需求。

DIP有效地减少了不同代码段之间的耦合。其思想是,尽管有许多实现方法,比如日志记录工具,但使用它的方式应该在时间上相对稳定。如果您可以提取一个表示日志记录概念的接口,那么这个接口在时间上应该比它的实现稳定得多,并且调用站点在维护或扩展日志记录机制时受更改的影响应该小得多。

通过使实现依赖于接口,您可以在运行时选择哪个实现更适合您的特定环境。根据具体情况,这可能也很有趣。

依赖倒置:依赖抽象,而不是具体。

控制反转:主要与抽象,以及主要如何成为系统的粘合剂。

以下是一些关于这方面的好文章:

https://coderstower.com/2019/03/26/dependency-inversion-why-you-shouldnt-avoid-it/

https://coderstower.com/2019/04/02/main-and-abstraction-the-decoupled-peers/

https://coderstower.com/2019/04/09/inversion-of-control-putting-all-together/

控制反转(IoC)是一种设计模式,在这种模式下,对象通过外部框架获得其依赖项,而不是向框架请求其依赖项。

使用传统查找的伪代码示例:

class Service {
    Database database;
    init() {
        database = FrameworkSingleton.getService("database");
    }
}

使用IoC的类似代码:

class Service {
    Database database;
    init(database) {
        this.database = database;
    }
}

国际奥委会的好处是:

您不依赖于中心 框架,所以这可以改变如果 想要的。 因为对象是被创建的 以注射方式使用为佳 接口,很容易创建单元 替换依赖项的测试 模拟版本。 解耦代码。