依赖反转原理[DIP]的意思是“抽象不应该依赖细节。细节应该取决于抽象”是什么意思?

时间:2018-10-17 14:19:08

标签: oop inversion-of-control solid-principles design-principles dependency-inversion

在问这个问题之前,我想先说一下stackoverflow中的this问题与我的问题非常相似,但是这个概念仍然不清楚,非常令人困惑。

我试图理解依赖倒置原理,但我无法完全理解它?

以下是DIP所说的两点

  

A。高级模块不应依赖于低级模块。都   应该依赖抽象。 B.抽象不应依赖   细节。详细信息应取决于抽象。

我能够掌握第一个要点,但我无法掌握第二个要点,因为两者看起来一样。在stackoverflow和其他站点中进行了大量搜索之后,我能够理解两者都在尝试说不同的话,但我无法获取。

我们来看一个例子:

让我们考虑SalaryCalculator类[高级模块],该类用于计算员工的工资。使用BonusCalculator [高级模块]来计算薪水,如下所示。由于SalaryCalculator使用的是BonusCalculator,因此违反了 的第一点。“高级模块不应依赖于低级模块。两者都应依赖抽象。”

enter image description here

因此我们在两者之间引入了抽象,如下所示:

enter image description here

详细信息[低级和高级模块]依赖于抽象,抽象不依赖于细节。那么在DIP中第二点试图说明什么?    如果两者相同,为什么将其分为两点?

如果有人给我一个代码示例,那将非常有用。

2 个答案:

答案 0 :(得分:3)

让我们进一步细分B部分。

抽象不应依赖于细节。这可能意味着您的接口声明(您的抽象)应避免包含具体类型。考虑一下distance(int X1, int Y1, int X2, int Y2)distance(Point A, Point B)之间的区别。如果您有在浮点,纬度/经度或极坐标系中测量的坐标怎么办?如果更改为3D空间怎么办?您必须重新实现每个使用距离函数的例程。

细节应该取决于抽象。尽可能地,继续使用抽象层来避免依赖于具体类型。

这是最大程度地减少变更的影响。您的代码对其他事物的依赖程度越低,则使其他代码进行更改的可能性就越大。

答案 1 :(得分:2)

这个问题的真正核心是为什么OOP有用,为什么抽象对于计算机科学如此重要。基本上,当我们想向软件用户隐藏复杂性(细节)时,我们使用抽象。

例如,如果我正在编写奖金计算器,而您正在编写工资计算器,我希望能够在不破坏您的应用程序的情况下对我的代码进行调整。

这要求我们俩都同意永远不变的特定抽象。我为您提供了访问代码功能的方法,并且向您保证,即使实现的“细节”随时间自由变化,调用这些方法也将始终为您提供相同的结果。

所以回到原始问题:

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

  • 通过“抽象化”低级模块(奖金计算器)中包含的功能,如果发现我的服务很垃圾,您应该可以相对容易地切换到其他人的奖金计算器。
  • 这是因为您通过抽象保护了自己免受代码“细节”的侵害。

B。 抽象不应依赖细节。详细信息应取决于抽象。

  • 如果您的抽象取决于我代码的细节,那么您将不得不重写所有内容以切换到新的奖金计算器!那会破坏目的。

代码示例(javascript):

  • 假设我们有一个称为“和”的抽象,它仅计算两个数字的和。您是此函数的使用者,并且想要像这样使用它:sum(2,2)= 4。
  • 现在说有两个不同的模块(函数)来计算总和。

    1. function sum(a, b) { return a + b }
    2. function sum(b, a) { return b + a }
  • 显然,这些函数是完全相同的,但请想象这是否是一个复杂的计算,具有许多不同的方法来完成结果,并且每种方法具有非常不同的运行时性能。使用相同的接口时,您可以自由地测试哪个函数更适合您:只需调用sum()即可。抽象不依赖于细节。

  • 通过这样做,您的高级模块也不再依赖于低级模块,因为您可以相对轻松地尝试使用其他低级模块。

抱歉,这个答案有点混乱。希望这会有所帮助!