2

今天我被问到一个我找不到答案的问题,所以我在这里寻求您的帮助!依赖倒置原则指出具体类和抽象都应该依赖于抽象,对吗?

尽管如此,我们仍然依赖于框架类,如IntegerString。关于为什么没问题有一个很好的答案吗?

我知道我们不应该仅仅因为它可能会发生微小的变化而重新发明轮子,而且我提到的这些特定类很可能永远不会以用户会注意到的方式发生变化(他们的界面不会改变)。

4

2 回答 2

2

另外一点,请注意您引用的元素实际上是 in java.lang,即没有 import 语句,因此可以说除了您使用 Java 之外,不依赖于使用这些类型引起的任何事物。

一旦你离开java.lang,我相信你通常最好应用DIP,即总是更喜欢使用aList<T>而不是使用a ArrayList<T>

问题是将跨“组件”(或模块/包...)边界的依赖关系限制为仅功能依赖关系(即抽象,Java 中的接口)。在某些时候,您确实需要具体的实现,这些实现必须至少使用一些数据结构来构建,即使它只是基本 int 类型的数组。这不违反 DIP。

@jaco0646 的回答中建议使用普通旧数据,不违反 DIP 是一种边界;在大多数情况下,您可以使用显式传递您正在考虑的结构字段的签名,而不是将它们打包到单个对象中;这种方法确实更通用,例如你可以在没有那个 POD 类的情况下实现它,也许依赖于一些关系 DBMS,你可以与用任何语言编写的代码进行交互等等......

然而在实践中,在签名中使用 POD 是有意义的,因此如果我向 POD 添加一个字段,这将自动传播到所有使用该结构的签名。其中一些函数可能不会使用新字段,因此我们现在给它们提供了太多信息(我们正在泄漏,关于严格的“需要知道”)。尽管如此,在许多情况下选择这种方法可能是一个务实的答案。

如果我们看一下例如 web 服务,一般倾向于认为 POD 在服务签名中不是问题,使用它们有助于保持客户端兼容,即使结构中出现了一些新字段。

于 2019-12-11T16:24:21.133 回答
2

在 OOP 中,对象是数据和行为的封装组合。数据被隐藏;行为暴露。DIP 应用的正是这些对象。理想情况下,这些对象应该在组合根中实例化,组合根是唯一依赖于对象具体类的组件。

显然,某些东西必须依赖于具体的类才能实例化它们。这通常是您的 DI 容器。这个想法是容器的唯一关注点是实例化具体类,因此其他一切都可以服从 DIP。

另一方面,与对象相反,我们有原始数据结构。这些类没有(必然)被封装,暴露了它们的数据,并且很少或没有行为。依赖于数据结构的具体类是可以的。这些不是 OOP 意义上的“对象”。DIP 不适用于数据结构。对具体数据结构的依赖应该是本地的;但是,不会暴露在拥有这些依赖项的对象之外。

请注意,您经常会在代码中看到“混合”:既充当对象又充当数据结构的类。他们暴露了他们的数据和行为。混合是两全其美的,无论你是否对它们应用 DIP,更大的问题是它们试图服务于两个相反的目的并违反封装。

于 2019-12-11T16:07:51.497 回答