开放/封闭原则与依赖性倒置原则有什么区别?

Mas*_*oud 6 oop design-patterns open-closed-principle solid-principles dependency-inversion

DIP声明:

  • 高级模块不应该依赖于低级模块.两者都应该取决于抽象.
  • 抽象不应该依赖于细节.细节应取决于抽象.

OCP声明:

软件实体(类,模块,函数等)应该是可以扩展的,但是关闭以进行修改.

我认为如果我们满足DIP,它也会涵盖OCP,那么,为什么我们将这两个原则分开呢?

C S*_*C S 16

Bob Martin 叔叔将开闭原则 (OCP) 和依赖倒置原则 (DIP) 作为两个 SOLID 原则进行推广,他自己表示,DIP 源于 OCP 和里氏替换原则的应用:

\n\n
\n

在本专栏中,我们将讨论 OCP 和 LSP 的结构含义。严格使用这些原则所产生的结构本身可以概括为一个原则。我把它称为\xe2\x80\x9c依赖倒置原理\xe2\x80\x9d(DIP)。

\n\n

Robert C. Martin,工程笔记本,C++ 报告,1996 年。

\n
\n\n

因此,您说每个 DIP 实例都是 OCP 实例是正确的,但 OCP 更为通用。这是我最近遇到的 OCP 但不是 DIP 的用例。许多 Web 框架都有信号的概念,一旦执行一个操作,就会触发一个信号。发送信号的对象完全不知道注册了该信号的侦听器。每次您想要向信号添加更多侦听器时,都可以在不修改发送者的情况下执行此操作。

\n\n

这显然是 OCP(“禁止修改,开放扩展”)的例证,但不是 DIP,因为发送者不依赖于任何东西,所以谈论它是否依赖于更抽象的东西或不那么抽象的东西是没有意义的。 。

\n\n

更一般地说,您可以说观察者模式( GoF 模式之一)描述了如何遵守 OCP 但不遵守 DIP。浏览 GoF 的书并看看哪些与 OCP 有关以及其中有多少与 DIP 无关会很有趣。

\n


Dav*_*rne 6

我认为坚持DIP原则更容易遵守OCP原则。但是,一个并不能保证另一个。

例如,我可以创建一个类,该类的方法采用Base. 如果base是抽象类,那么我将坚持 DIP,因为我已将依赖关系倒转为调用者。但是,如果该方法中的代码执行以下操作:

if (base is derived)
    (derived)base.DoSomethingSpecificToDerived;
elsif (base is evenMoreDerived)
    (evenMoreDerived)base.DoSomethingSpecificToEvenMoreDerived;
Run Code Online (Sandbox Code Playgroud)

然后它不符合 OCP,因为我每次添加新派生类时都必须修改它。

这是一个非常人为的例子,但你明白我的意思。

  • 但是在您的示例中,高级模块(您的代码在其中)取决于低级实现(派生,甚至更多派生),因此我认为您的示例也违反了 DIP。 (3认同)

Ali*_*Ali 5

DIP告诉您如何组织依赖项.它不会告诉你,当你与一个特定的接口完成.

粗略地说,OCP的信息是拥有完整但简约的界面.换句话说,它告诉您何时完成了界面,但它没有告诉您如何实现这一点.

在某种意义上,DIP和OCP是正交的.


那么,为什么我们将这两个原则分开呢?

至于设计模式和命名原则,几乎所有这些都有以下共同点:

  1. 找出变化的东西并封装(隐藏)它.

  2. 更喜欢继承聚合.

  3. 设计到接口.

即使命名的模式和原则在某种意义上部分重叠,它们也会告诉你比上述三个一般原则更具体的(在更具体的情况下).

  • 不太清楚“当你完成界面时”和“如何实现这一点”是什么意思。 (3认同)