问题描述
我目前正在阅读一本关于依赖倒置原则的优秀教程
https://www.baeldung.com/java-dependency-inversion-principle
虽然我想了很长时间,但我还是无法解释一些事情
DIP 定义的相关部分:“高级模块不应该依赖于低级模块。两者都应该依赖于抽象。”
在第 3.1 点“设计选择和 DIP” 中,作者通过一个示例介绍了该原理,其中 StringProcessor
类使用 StringReader
和 StringWriter
组件并使用接口/类和包提供多种设计选择。我的问题是选择 2 是
"StringReader
和 StringWriter
是与实现放在同一个包中的接口。StringProcessor
现在依赖于抽象,但低级组件不依赖。我们还没有实现依赖倒置"
StringProcessor
是 “高级组件”,它依赖于 “抽象” 即 StringReader
和 StringWriter
接口,从而从一方面实现 DIP 定义,这很清楚。现在给出在第一句中提到的文章“实现”中使用的术语,例如ConcreteStringReader
和 ConcreteStringWriter
类将是 “低级组件”,我只是无法理解它们如何不依赖于 ”抽象” 即在它们实现的接口上,无论包含哪些包
显然,从代码组织的角度来看,将实现与其接口放在同一个包中可能不是最好的,但是这如何违反上面依赖于抽象的逐字 DIP 定义目前超出了我的理解
也许对这个主题有更深入理论知识的人可能会帮助我
解决方法
隐含的一般概念是一个包等同于一个抽象级别。因此,在第 3.1.2 节中,具体实现由于在同一个包中而“拥有”它们的抽象;因为在发布包的任何地方,这些实现都随处可见。共享包的类之间的耦合在一定程度上体现在语法上,即使在 Java 8 中也是如此。例如,import
语句不是必需的,并且具有默认访问修饰符的类和方法是可见的。
不过,根据 JPMS 功能,更容易看到第 3.1.2 节中的缺陷。模块在包级别定义,将包是单个抽象级别的概念形式化。就 DIP 而言,依赖关系也在包级别考虑。如果一个包包含具体的实现,它被认为是低级,并且不应该有传入的依赖项。
深入探讨该主题的整本书是Java Application Architecture: Modularity Patterns。
,"StringReader 和 StringWriter 是放置在同一个接口中的接口 与实现一起打包。 StringProcessor 现在依赖于 抽象,但低级组件没有。我们还没有达到 依赖关系倒置"
虽然它确实不是 DIP,但 IMO 的解释是错误的。问题是作者没能分辨出类/组件和层/包/模块之间的区别。 DIP 是一个只适用于模块间关系的原则,对于单个模块显然不适用。
至于第 4 点,
同样,第 4 项是一个更加解耦的 DIP 实现。在这 模式的变体,既不是高级组件也不是 低级的拥有抽象的所有权。
我们在这里需要非常小心,因为“所有权”不仅仅是“在同一个包裹中”。
例如这将是 DIP 违规