Java 静态工厂和依赖注入

Java 静态工厂和依赖注入,java,dependency-injection,Java,Dependency Injection,在有效的Java(书籍)中,建议使用静态工厂 另一方面,建议保持依赖关系的显式性,例如使用DI 但是当我想要使用静态工厂时,这种明确性将被跳过,因为将通过调用静态工厂方法来接收对象实例。使用静态工厂方法,我不必传入包含静态工厂的对象 这两件事怎么能同时进行呢?真是个好问题。 静态工厂确实有这个缺点(除其他外):它们不是显式的,因此不能用作可切换的依赖项。 我不认为您可以让这两件事一起工作,因为静态方法与类相关联,而依赖项注入与实例相关联。 因此,这是一种设计选择。 就我个人而言,我使用工厂方法,

在有效的Java(书籍)中,建议使用静态工厂

另一方面,建议保持依赖关系的显式性,例如使用DI

但是当我想要使用静态工厂时,这种明确性将被跳过,因为将通过调用静态工厂方法来接收对象实例。使用静态工厂方法,我不必传入包含静态工厂的对象

这两件事怎么能同时进行呢?

真是个好问题。
静态工厂确实有这个缺点(除其他外):它们不是显式的,因此不能用作可切换的依赖项。

我不认为您可以让这两件事一起工作,因为静态方法与类相关联,而依赖项注入与实例相关联。
因此,这是一种设计选择。

就我个人而言,我使用工厂方法,因为我不想允许显式设置工厂返回的依赖项。
这是您想要掌握对象创建的情况:一致性、缓存等。。。您希望提供一个清晰的API。 这是一个非常直接的保证方式。
使用依赖项注入设置对象不会提供此功能。

一般来说,我这样做是为了那些既不想提供替代实现也不想在单元测试期间模拟的类。
这是我想要掌握创建的业务/模型类的情况,也是一些“实用”类的情况。
但是,一旦需要显式设置依赖项,我就会重构静态工厂,使其能够显式设置依赖项。
如果始终需要创建对象的主对象,我会将静态工厂转换为注入的实例工厂。

否则,我将直接注入工厂返回的对象。
问题有两个方面:

  • 正在创建的对象
  • 正在执行此操作的对象 创造
  • 工厂、构造函数和自动解析容器是改变对象创建方式的手段(问题2)。这与对象如何创建自身完全不同(问题1)

    作为一般启发:

  • 正在创建的对象在如何构造方面应该尽可能灵活,并且应该在其构造函数中显式地公布其所有依赖项(即使构造函数是私有的,并且创建者使用工厂)

  • 创建者应该与他们创建的对象分离,以满足应用程序保持灵活性的需要。高度稳定的依赖关系可以直接依赖。不应更改或替换可能发生变化的依赖项

  • 静态工厂、实例工厂、构造函数和容器自动解析之间的区别主要是语法。最大的区别在于语义表达(它向开发人员传达程序结构的信息)和在运行时解析不同实现的能力


    为了回答你的核心问题,这两件事可以结合在一起,因为它们是解决问题的两个方面。您可以同时使用它们。

    因此,如果对我来说更重要的是拥有可切换的依赖项,那么我应该使用DI并省略静态工厂,对吗?我会这么做。令人恼火的是,你没有其他答案,也没有我的认可。你能解释得更具体一点吗?我能想象的唯一方法就是通过DI注入工厂。但是编译器不支持实践。如果我省略了注入,我仍然可以调用静态工厂方法。在不了解特定技术堆栈的情况下,很难变得更加具体。在这段代码中,我可以使用如下静态工厂方法在容器中注册:
    services.AddScoped(x=>Accounts.Create(x.GetService())
    在这种情况下,
    Accounts.Create()
    将是一个静态工厂方法。如果您想了解特定堆栈的详细信息,可以使用导致问题的代码打开一个新问题。可能您正在使用带注释的Spring,或者类似的麻烦事。大多数自动布线工具都有可以使用的高级功能。