依赖倒置原则

最后一个SOLID规则是依赖关系反转原理。 根据罗伯特·马丁(Robert Martin)的《敏捷软件开发:原则,模式和实践》,该原则定义为:

1)高级模块不应依赖于低级模块。 两者都应依赖抽象。2)抽象不应依赖细节。 细节应取决于抽象

这很多,所以让我们分别看一下每个规则。

High Level Modules Shall not Depend on Low-Level Modules

让我们看一个非常简单的Java示例:

In this example, Monitor is dependent on DisplayPortCable and DisplayPortCable is dependent on Laptop. If Monitor wants to use a different cord, say an HDM一世 or VGA cord, we will be forced to change Monitor directly. We could give Monitor multiple constructors for each cord type; we could also create a base class that holds the behavior for all the cords. However, these approaches aren't desirable as it leaves the class rigid and cumbersome to expand and it could become bloated. A base class may seem like a good idea, but it's too tempting to add behavior for all the cords in one place and simply extend it to the newly created classes. This bloat tends to break the interface segregation principle. The same holds true for the relationship between DisplayPortCable and Laptop.

在像Java这样的静态类型语言中,最好使用接口(或C ++中的虚拟类)来反转依赖关系。 接口允许我们为高级类定义一个低级类型(例如监控)使用。

Inverting a Dependency

在反转依赖项时,我们希望所依赖的类(在我们的示例中)DisplayPort电缆和笔记本电脑)改为依赖于接口。 继续我们的示例,DisplayPort电缆和监控看起来像这样:

从示例中,我们为视讯电缆并实施我们计划用于的电缆监控。 代替监控仅限于接受DisplayPort电缆现在可以接受任何视讯电缆。

我们的代码中仍然存在依赖项,因为视讯电缆取决于笔记本电脑。 这有助于将我们带入该原理的下一部分。

Abstractions Shall not Depend on Details. Details Shall Depend on Abstraction

在考虑类的细节时,我喜欢认为细节意味着类的行为和属性。 在我们的示例中,这意味着#connect()和#connectedDevice。 虽然我们DisplayPort电缆是抽象的,它仍然依赖于笔记本电脑。 我们提出的问题与我们之前提出的问题相同。 如果一个视讯电缆想连接到桌面或一个手机代替笔记本电脑?

因此,我们像以前那样反转了依赖关系。

Dynamic vs Static Approaches to Dependency Inversion

上面的示例是用Java完成的。 静态类型的语言通常具有定义抽象接口的具体方式。 但是,在动态类型的语言中,抽象类的想法很难实现,因为这样做的工具通常不是该语言的功能。 在这种情况下,我们可以使用一种称为鸭子打字的技术。

鸭子类型化的想法是,如果类的行为以特定的方式行走并以特定的方式交谈,则可以将该方式抽象为从属类。

接口依赖类关键字方法用于依赖关系反转和鸭子类型之间的区别在于,前者以契约形式编写,其中行为被明确定义和执行。 后者没有明确定义,并且随着在类中使用更多对象类型而变得明显。 如果要将上面的代码转换为Ruby,鸭子类型将不会很明显,因为只有一种对象类型取决于抽象。

随着我们添加更多类,问题变得更加明显。

由于没有明确的合同,我们可以在我们的新类中使用任何旧接口,只需询问以下类型videoConnector并使用定义的任何接口。 但是,这不仅使监控很难扩展(因为我们必须手动添加新条件才能理解新类型),但这导致监控了解其他类的内部运作方式,这些行为直接违反了该原理。监控必须依赖于它所接收的对象的抽象。监控不必关心对象的类,而只关心其行为。

为此,我们必须有意识地确保类具有一致的接口,并且它们依赖于此接口。 在我们的例子中,我们必须规定#connectToDevice()会期望videoConnector拥有#connect()要么#connectToSomething()行为。

In Conclusion

依赖倒置可能很棘手。 但是,它可以使班级更加灵活,并训练我们从行为的角度而不是从构造的角度来考虑班级。

from: https://dev.to//naomidennis/dependency-inversion-principle-1kbj

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值