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