【问题标题】:Proper Class Construction: Using Multiple Hard Dependencies正确的类构造:使用多个硬依赖
【发布时间】:2016-12-08 19:43:10
【问题描述】:

我正在尝试通过将大型类(2000 多行)重构为更小的、有凝聚力的类(约 200 行),将单一职责原则集成到我的 Java 代码中。但是我对如何正确减少类之间的耦合感到困惑,因为 某些类似乎必然会通过 new 关键字创建多个“硬依赖”。

我主要通过构造函数使用依赖注入,然后是 setter 方法,或者接受依赖作为参数并在方法主体内的其他逻辑中使用它的方法(不仅仅是简单的this.val = val; setter。

IntelliJ 的自动重构实例化这个新提取的类,并通过 this 引用将其传递(注入)到 LoadController。如果我必须重构一个 2000 行的类,当然每次我提取一个新类时都会发生这种自动实例化 + 注入。下面的 LoadController 是程序主阶段的 JavaFX 控制器类,它作为各种功能的起点:

public class LoadController{
        private final DBConnection dbConnection = new DBConnection(this); 
        private final UpdateLabels updateLabels = new UpdateLabels(this);
        private final OpenCloseMenu openCloseMenu= new OpenCloseMenu (this);
        private final CreateVBox createVBox= new CreateVBox (this, dbConnection);
        private final ...
        private final ...
}

这是错的吗?我的理解是,大的、独立的函数应该在它们自己的类中......但是有些类必须像上面那样具有多个硬依赖关系,以便“引导”使用各种其他类之间的逻辑流。

【问题讨论】:

    标签: java dependency-injection constructor parameter-passing single-responsibility-principle


    【解决方案1】:

    如果您正在对 JavaFX 控制器进行依赖注入,您可能希望考虑使用类似 Gluon Ignite 的东西来帮助您。

    Gluon Ignite 允许开发人员在他们的 JavaFX 应用程序中使用流行的依赖注入框架,包括在他们的 FXML 控制器中。 Gluon Ignite 在几个流行的依赖注入框架上创建了一个通用抽象

    您选择使用的注入框架(例如 Guice 或 Spring)将负责创建可注入组件(例如您不调用 new)并将相关引用注入您的代码中(例如您不需要写dbConnection = <some value>)。注入框架将包含大量文档和博客文章,说明它的工作原理以及如何最好地使用它,因此对此的全面讨论超出了本答案的范围。

    Gluon Ignite 的替代品是 afterburner.fx,它与 @Inject 类似,但使用了一个小型自定义实现,因此更轻量级(并且功能稍弱),然后是更成熟的依赖注入框架(非常简单使用)。

    这只是一种选择,还有其他方法可以处理这个问题,但是当您声明您希望使用 JavaFX 执行依赖注入时,似乎可以使用经过验证的框架来执行此操作,而不是尝试滚动您的自己的实现。

    一些类必须像上面那样有多个硬依赖,以便“引导”各种其他类的使用之间的逻辑流。

    使用 Guice 之类的东西,您可以提供一个定义接口类型和实现之间的绑定的模块。这些绑定告诉 Guice 如何构建依赖项,因此您无需在类中对依赖项进行硬编码。有关模块示例,请参阅 Guice getting started guide 中的 BillingModule。如果你需要多个可注入对象的实例,你可以在 Guice 中使用Providers。 Spring 有类似的概念,但名称不同。


    决定是否使用依赖注入框架是在没有注入框架的情况下需要做的工作与将框架集成到应用程序的额外时间和复杂性之间的权衡。因此,是否使用某个框架的决定需要由您做出的架构决策,对于每个应用程序来说,使用此类框架是否合理并没有一个通用的正确或错误答案。

    我认为使用注入框架对我的要求来说是多余的,那么我没有做任何本质上不正确的事情,因为在某些类中有多个硬依赖项,如上所示?

    嗯,依赖关系需要在某个地方定义。在推断或集中位置,例如依赖注入系统使用或本地给定类,如您可能从传统的responsibility driven design approach 确定的那样。因此,您不一定会因为硬依赖而做错任何事情。并不总是需要依赖注入等抽象解耦模式。

    诀窍在于确定哪些依赖项在哪里以及如何管理它们。通常它只是显而易见的并且自然地从问题域中消失,有时像CRC modeling 这样的技术可以帮助构建依赖关系。

    相关文章:

    我的假设是,我可以使用 new 将大型类重构为更小的、有凝聚力的类,其中一些类具有多个硬依赖项。

    是的,你当然可以这样做。

    注入框架是否可以在项目生命周期的后期集成,而不是在可能还不需要的早期集成?

    是的,它可以。这样做需要做一些工作,但如果应用程序结构良好,就不是那么困难了。换一种方式尝试从已经基于它的应用程序和库中删除依赖注入框架的使用会更加困难。

    相关:

    【讨论】:

    • 感谢jewelsea,所以你是说如果我决定使用注入框架对我的要求来说是多余的,那么我不会通过多个硬某些类中的依赖关系,如上所示?我的假设是我可以使用new 将我的大类重构为更小的、有凝聚力的类,其中一些类具有多个硬依赖项。注入框架是否可以在项目生命的后期集成,而不是在可能还不需要的早期集成?
    猜你喜欢
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多