1

我理解在单个模块中工作时的依赖倒置,但是当我有跨模块依赖时我也想应用它。在下图中,我有一个现有的应用程序,我需要为参考数据服务实现一些新要求。我想我会创建一个新的 jar(将来可能是一个独立的服务)。第一个图显示了我过去处理此类事情的正常方式。referencedataservices jar 有一个接口,应用程序将使用该接口调用它。

第二个图显示了我尝试使用 DIP,应用程序现在拥有它的抽象,因此它不会因为参考数据服务发生变化而发生变化。这似乎是一个错误的设计,因为它创建了一个循环依赖。MyApp 依赖于referencedataservices jar,referencedataservices jar 依赖于MyApp。

所以第三个图通过创建一个额外的抽象层回到了更正常的依赖关系。我对吗?或者这真的不是 DIP 的目的吗?有兴趣了解其他方法或建议。

,依赖倒置图

4

2 回答 2

1

第二个示例通过将实现与抽象分离,走上了正轨。为了实现模块化,具体类不应与其抽象接口位于同一包(模块)中。

第二个例子的错误在于客户端拥有抽象,而服务拥有实现。这两个角色必须颠倒过来:服务自己的接口;客户自己的实现。通过这种方式,服务提供了一个合同 (API) 供客户端执行。该服务保证与任何遵循其 API 的客户端进行交互。在依赖倒置方面,客户端将依赖注入到服务中。

Kirk K. 是 Java 模块化方面的权威。他有一个博客,最终变成了一关于这个主题的书。他的博客目前似乎不见了,但我能够在 Wayback Machine 中找到它。我想您会对名为Applied Modularity的四部分系列特别感兴趣。关于 DIP 的其他方法或替代方案,请查看Fun With Modules,其中涵盖了其中的三个。

于 2015-09-07T13:40:14.407 回答
0

在您提出的第二种方法中,如果您将RefDataSvc抽象移动到单独的包中,您将打破循环并且referencedataservices包仅使用带有RefDataSvc抽象的包。

包中除Composition Root之外的其他代码MyApp也应依赖于RefDataSvc. 然后,在应用程序的组合根中,您应该组合应用程序中所需的所有依赖项。

于 2015-09-07T07:20:16.260 回答