我最近在 Robert.C.Martin 的优秀著作 Agile Principals, Patterns and Practices in C# 中读到了 Dependency-Inversion Principal。然而,我觉得我不完全理解这个原则的一个方面。
Robert 解释说,当高层模块依赖于低层模块时,低层模块的变化也会导致高层模块发生变化。他通过以下示例演示了这一点:
public class Button
{
private Lamp lamp;
public void Poll(){
if(/*some condition*/)
Lamp.TurnOn();
}
}
关于这段代码,Robert 说“Button 类直接依赖于 Lamp 类。这种依赖意味着 Button 将受到 Lamp 更改的影响。”
在我看来,我们可能会对 Lamp 类进行两种可能的更改:
1)我们可能想改变类的内部实现但不影响公共接口。
2) 我们可能决定更改公共接口,将参数传递给 TurnOn 方法。
我不明白的是,在第一种情况下,为什么我们的更改会导致 Button 类发生更改?Lamp 的公共接口没有改变,那么为什么 Button 需要改变呢?
在第二种情况下,我可以看到这需要我们更改 Button。但在这种情况下,依赖抽象如何改变这一点?当然,如果我有正当理由将接口更改为 Lamp,那么我也会更改 Lamp 和 Button 所依赖的抽象接口。在这种情况下,无论如何我都必须更改 Button,因为它所依赖的抽象已经改变。
我意识到 DIP 还有其他好处,例如更高级别模块的可重用性、更高级别模块对接口的所有权以及在运行时选择依赖项实现的能力,但是我很难理解 DIP 如何减少对依赖项的需求当与较低级别模块的接口发生更改和/或依赖模块中的内部更改可能导致更高级别模块中的更改时,要更改的模块。