简体   繁体   English

静态工厂和依赖注入

[英]Static factories and dependency injection

In Effective Java (book), static factories are recommended. 在Effective Java(书籍)中,建议使用静态工厂。

On the other hand, keeping dependencies explicit, for example by using DI, is recommended. 另一方面,建议保持依赖关系明确,例如使用DI。

But when I want to use a static factory, this explicitness will be skipped, because object instances will be received by calling the static factory method. 但是当我想使用静态工厂时,将跳过此显式性,因为将通过调用静态工厂方法来接收对象实例。 With static factory methods, I won't have to pass in the object containing the static factory. 使用静态工厂方法,我不必传入包含静态工厂的对象。

How can these two things go together? 这两件事怎么结合在一起呢?

Really good question. 真好问题。
Static factories have indeed this drawback (among others): they are not explicit and consequently they cannot be used as switchable dependencies. 静态工厂确实存在这个缺点(其中包括):它们不是显式的,因此它们不能用作可切换的依赖项。

I don't think that you can make the two things work together as a static method is associated to the class while the dependency injection is associated to instances. 我不认为你可以让这两件事一起工作,因为静态方法与类相关联,而依赖注入与实例相关联。
So it is a choice of design. 所以它是一种设计选择。

Personally, I use the factory method as I don't want to allow to set explicitly the dependency returned by the factory. 就个人而言,我使用工厂方法,因为我不想允许显式设置工厂返回的依赖项。
It is the case as you want to master the objects creation : consistency, caching, and so for... and you want to provide a clear API. 在这种情况下,您希望掌握对象创建:一致性,缓存等......并且您希望提供一个清晰的API。 It is a very straight way to guarantee that. 这是一种非常直接的方式来保证这一点。
Setting an object with dependency injection will not provide that. 设置具有依赖注入的对象不会提供。

Generally, I did it for classes that I don't want neither to provide alternative implementations nor to mock during unit tests. 一般来说,我是为那些我不希望既不提供替代实现也不想在单元测试期间进行模拟的类做的。
It is the case of business/model classes which I want to master the creation and also for some "utility" classes. 我希望掌握创建的业务/模型类以及一些“实用程序”类的情况。
But as soon as the need to explicitly set the dependency happens, I refactor the static factory in something that allows to set the dependency explicitly. 但是一旦需要显式设置依赖关系,我就会将静态工厂重构为允许显式设置依赖关系的东西。
If the master of the objects creation is always necessary, I transform the static factory into an instance factory that I inject. 如果始终需要创建对象的主体,我将静态工厂转换为我注入的实例工厂。
Otherwise I inject directly the object that was returned by the factory. 否则我直接注入工厂返回的对象。

There are two sides of the problem: 这个问题有两个方面:

  1. The object that is being created. 正在创建的对象。
  2. The object that is doing the creating. 正在进行创建的对象。

Factories, constructors, and auto-resolving containers are means of changing the way an object can be created (problem 2). 工厂,构造函数和自动解析容器是改变对象创建方式的手段(问题2)。 That is entirely separate from how an object allows itself to be created (problem 1). 这与对象允许自己创建的方式完全不同(问题1)。

As a general heuristic: 作为一般启发式:

  1. Objects that are being created should be as flexible as possible in terms of how they can be constructed, and should explicitly advertise all their dependencies in their constructors (even if the constructors are made private and a factory is used by creators). 正在创建的对象在构造方式方面应该尽可能灵活,并且应该在其构造函数中明确地宣传它们的所有依赖项(即使构造函数是私有的,创建者也使用工厂)。

  2. Creators should be as decoupled from the objects they created as your application needs to maintain its flexibility. 创建者应该与他们创建的对象分离,因为应用程序需要保持其灵活性。 Highly stable dependencies can be depended on directly. 高度稳定的依赖关系可以直接依赖。 Dependencies that may change or be replaced should not 可能会改变或被替换的依赖性不应该

Differences between static factories, instance factories, constructors, and auto-resolution by container are largely just syntax. 静态工厂,实例工厂,构造函数和容器自动解析之间的差异主要只是语法。 The biggest differences are semantic expression (what it communicates to a developer about the structure of the program) and the ability to resolve different implementations at runtime. 最大的区别是语义表达(它与开发人员就程序结构进行通信)以及在运行时解析不同实现的能力。

To answer your core question, the two things can go together because they are solutions to separate halves of the problem. 要回答你的核心问题,这两件事可以结合在一起,因为它们是分离问题的一半的解决方案。 You can use them both together. 你可以一起使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM