DIP原则的表述如下:
- 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。
- 抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。
OCP原则的表述如下:
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
我认为如果我们满足了DIP原则,也就涵盖了OCP原则,那么为什么要将这两个原则分开呢?
DIP原则的表述如下:
- 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。
- 抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。
OCP原则的表述如下:
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
我认为如果我们满足了DIP原则,也就涵盖了OCP原则,那么为什么要将这两个原则分开呢?
我认为遵循DIP原则可以更容易地符合OCP原则,但是一个并不能保证另一个。
例如,我可以创建一个类,其中有一个方法,该方法需要一个名为base
的参数。如果base
是一个抽象类,那么我就遵循了DIP原则,因为我已经将依赖倒置给了调用者。然而,如果该方法中的代码执行了以下操作:
if (base is derived)
(derived)base.DoSomethingSpecificToDerived;
elsif (base is evenMoreDerived)
(evenMoreDerived)base.DoSomethingSpecificToEvenMoreDerived;
如果每次添加新的派生类都需要修改它,那么它就不符合OCP标准。
这只是一个非常牵强的例子,但你明白我的意思。
@CS的回答很好。总结一下:
public abstract class MyClass {
DependencyOne d1;
DependencyTwo d2;
MyClass() {
d1 = new DependencyOne();
d2 = new DependencyTwo();
}
}
@Deprecated
注释来标记代码,该代码开放于修改,从而违反了OCP。同时,这段代码在抽象和依赖方面可能是完全符合DIP的。某些库使用一个@Beta
注释来达到类似的效果。OCP使得依赖类易于使用。OCP通过将旧实现与新版本解耦,实现接口的异步使用。即使面临其他目的的变化,它也允许依赖它的事物继续依赖它。这样一来,一个类永远不必关心谁在调用它。
DIP有几个作用。它使得依赖外部类变得容易。依赖注入通过鼓励创建职责与消费职责的分离,从而实现了依赖项的替换。模式规定,应该在外部提供要使用的外部依赖项,而不是创建它。最终,这鼓励编写幂等代码(不改变外部状态的代码)。幂等代码很好,因为可以验证它只做了立即可见的事情。它没有外部副作用。它非常易于测试、理解和阅读。