在问这个问题之前,我想先说一下stackoverflow中的this问题与我的问题非常相似,但是这个概念仍然不清楚,非常令人困惑。
我试图理解依赖倒置原理,但我无法完全理解它?
以下是DIP所说的两点
A。高级模块不应依赖于低级模块。都 应该依赖抽象。 B.抽象不应依赖 细节。详细信息应取决于抽象。
我能够掌握第一个要点,但我无法掌握第二个要点,因为两者看起来一样。在stackoverflow和其他站点中进行了大量搜索之后,我能够理解两者都在尝试说不同的话,但我无法获取。
我们来看一个例子:
让我们考虑SalaryCalculator类[高级模块],该类用于计算员工的工资。使用BonusCalculator [高级模块]来计算薪水,如下所示。由于SalaryCalculator使用的是BonusCalculator,因此违反了 的第一点。“高级模块不应依赖于低级模块。两者都应依赖抽象。”
因此我们在两者之间引入了抽象,如下所示:
详细信息[低级和高级模块]依赖于抽象,抽象不依赖于细节。那么在DIP中第二点试图说明什么? 如果两者相同,为什么将其分为两点?
如果有人给我一个代码示例,那将非常有用。
答案 0 :(得分:3)
让我们进一步细分B部分。
抽象不应依赖于细节。这可能意味着您的接口声明(您的抽象)应避免包含具体类型。考虑一下distance(int X1, int Y1, int X2, int Y2)
和distance(Point A, Point B)
之间的区别。如果您有在浮点,纬度/经度或极坐标系中测量的坐标怎么办?如果更改为3D空间怎么办?您必须重新实现每个使用距离函数的例程。
细节应该取决于抽象。尽可能地,继续使用抽象层来避免依赖于具体类型。
这是最大程度地减少变更的影响。您的代码对其他事物的依赖程度越低,则使其他代码进行更改的可能性就越大。
答案 1 :(得分:2)
这个问题的真正核心是为什么OOP有用,为什么抽象对于计算机科学如此重要。基本上,当我们想向软件用户隐藏复杂性(细节)时,我们使用抽象。
例如,如果我正在编写奖金计算器,而您正在编写工资计算器,我希望能够在不破坏您的应用程序的情况下对我的代码进行调整。
这要求我们俩都同意永远不变的特定抽象。我为您提供了访问代码功能的方法,并且向您保证,即使实现的“细节”随时间自由变化,调用这些方法也将始终为您提供相同的结果。
所以回到原始问题:
A。 高级模块不应依赖于低级模块。两者都应依赖抽象。
B。 抽象不应依赖细节。详细信息应取决于抽象。
代码示例(javascript):
现在说有两个不同的模块(函数)来计算总和。
function sum(a, b) { return a + b }
function sum(b, a) { return b + a }
显然,这些函数是完全相同的,但请想象这是否是一个复杂的计算,具有许多不同的方法来完成结果,并且每种方法具有非常不同的运行时性能。使用相同的接口时,您可以自由地测试哪个函数更适合您:只需调用sum()即可。抽象不依赖于细节。
抱歉,这个答案有点混乱。希望这会有所帮助!