简体   繁体   中英

Static factories and dependency injection

In Effective Java (book), static factories are recommended.

On the other hand, keeping dependencies explicit, for example by using DI, is recommended.

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. 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). That is entirely separate from how an object allows itself to be created (problem 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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