当前位置 : 主页 > 手机开发 > 其它 >

Dependency-Inversion Principal(DIP)如何减少在依赖模块发生变化时对依赖模块进行更改

来源:互联网 收集:自由互联 发布时间:2021-06-22
我最近在Robert.C.Martin的优秀着作Agile Principals,C#中的模式和实践中读到了依赖性 – 倒置主体.然而,这个原则的一个方面我觉得我不完全理解. Robert解释说,当高级模块依赖于较低级别的模
我最近在Robert.C.Martin的优秀着作Agile Principals,C#中的模式和实践中读到了依赖性 – 倒置主体.然而,这个原则的一个方面我觉得我不完全理解.

Robert解释说,当高级模块依赖于较低级别的模块时,较低级别模块的更改可能会导致更高级别的模块也发生变化.他通过以下示例演示了这一点:

public class Button
{
   private Lamp lamp;
   public void Poll(){
      if(/*some condition*/)
         Lamp.TurnOn();
   }
}

关于这段代码罗伯特说:“Button类直接依赖于Lamp类.这种依赖性意味着Button会受到Lamp变化的影响.”

正如我所看到的,我们可能会对Lamp类进行两种可能的更改:

1)我们可能想要更改类的内部实现,但不会影响公共接口.

2)我们可能决定更改公共接口以将参数传递给TurnOn方法.

我不明白的是,在第一种情况下,为什么我们的更改会导致Button类的更改? Lamp的公共接口没有改变,为什么Button需要改变?

在第二种情况下,我可以看到这将需要我们更改Button.但在这种情况下,取决于抽象如何改变这一点?当然,如果我有正当理由将接口更改为Lamp,那么我也将改变Lamp和Button所依赖的抽象中的界面.在这种情况下,我必须改变Button,因为它依赖的抽象已经改变.

我意识到DIP还有其他好处,例如更高级别模块的可重用性,更高级别模块的接口所有权以及在运行时选择依赖项实现的能力,但是我很难理解DIP如何减少依赖的需求当到较低级别模块的接口改变时改变的模块和/或从属模块中的内部改变可能导致更高级别模块的改变的原因.

我相信DIP为这个例子带来的重要区别是界面的所有权.特别是哪个层拥有接口,其中Button是客户端而Lamp是服务器.

在具体类Lamp的依赖项中,接口(.TurnOn())归Lamp类(服务器)所有.因此,可以决定仅根据服务器的需要更改.TurnOn()方法,因为它拥有该方法,这将需要后续更改Button类(客户端).

当接口被抽象为ISwitchableDevice接口/抽象类时,所有权将转移到客户端或共享层.因此,对接口的更改不能直接由服务器需求驱动,可以在不更改接口的情况下对Lamp类(由服务器拥有)进行任何更改.如果需要更改ISwitchableDevice接口,那么这将由客户端或共享层的需求驱动.

网友评论