DIP声明:
- 高级模块不应依赖于低级模块。两者都应该取决于抽象。
- 抽象不应该依赖于细节。细节应取决于抽象。
OCP声明:
软件实体(类,模块,函数等)应该是开放的 用于扩展,但已关闭以进行修改。
我认为如果我们满足DIP,它也将覆盖OCP,那么,为什么我们将这两个原则分开呢?
答案 0 :(得分:5)
DIP告诉您 如何组织依赖项。它没有告诉你何时你完成了特定的界面。
粗略地说,OCP的信息是拥有完整但简约的界面。换句话说,它告诉你何时你完成了一个界面,但它没有告诉你如何来实现这一点。
在某种意义上,DIP和OCP是正交的。
那么,为什么我们将这两个原则分开呢?
至于设计模式和命名原则,几乎所有这些原则都有:
查找不同的内容并将其封装(隐藏)。
首选聚合继承。
设计接口。
即使指定的模式和原则在某种意义上部分重叠,它们也会告诉你比上述三个一般原则更具体的(在更具体的情况下)。
答案 1 :(得分:4)
我认为遵守DIP原则可以更容易地遵守OCP原则。但是,一方不保证另一方。
例如,我可以创建一个具有参数Base
的方法的类。如果base
是一个抽象类,那么我正在坚持DIP,因为我已将依赖关系转换为调用者。但是,如果该方法中的代码执行类似的操作:
if (base is derived)
(derived)base.DoSomethingSpecificToDerived;
elsif (base is evenMoreDerived)
(evenMoreDerived)base.DoSomethingSpecificToEvenMoreDerived;
然后它不符合OCP标准,因为每次添加新衍生产品时我都必须对其进行修改。
这是一个非常人为的例子,但你明白了我的观点。
答案 2 :(得分:0)
OCP使依赖类易于使用。 OCP通过将旧实现与较新版本分离来实现接口的异步使用。即使面对其他目的的变化,它也允许依赖它的东西继续依赖它。这样一个班级就不必关心谁在呼唤它。
DIP做了两件事。它使得依赖外部类很容易。依赖注入通过鼓励创建职责与消费分离来实现依赖性的替换。该模式不是创建要使用的外部依赖项,而是声明它应该在外部提供。最终,这会鼓励幂等的代码(不改变外部状态的代码)。幂等代码很好,因为可以验证它只能立即显示。它没有外部副作用。它非常可测试,可理解且易读。
答案 3 :(得分:0)
鲍勃·马丁叔叔将开放-封闭原则(OCP)和依赖倒置原则(DIP)推广为SOLID原则中的两项,states himself认为DIP源于OCP和Liskov替代原则的应用:
在本专栏中,我们讨论OCP和 LSP。严格使用这些结构的结构 原则本身可以概括为一个原则。我打电话 它是“依赖倒置原则”(DIP)。
Robert C. Martin,工程笔记本,C ++报告,1996年。
因此,您正确地指出DIP的每个实例都是OCP的实例,但是OCP更为通用。这是OCP的用例,但不是我最近遇到的DIP。许多Web框架都有信号的概念,一旦执行一项操作,就会触发信号。发送信号的对象完全不知道向该信号注册的侦听器。每次您想向信号添加更多的侦听器时,都可以这样做,而无需修改发送者。
这显然是OCP(“封闭修改,开放扩展”)的示例,而不是DIP,因为发件人不依赖任何东西,因此谈论它是否依赖于更抽象或更抽象的东西没有意义。 。
通常,您可以说观察者模式(GoF patterns之一)描述了如何遵守OCP而不是DIP。仔细阅读GoF书,看看哪些与OCP有关,以及哪些与DIP不相关,这很有趣。