Use Factory Method in Java when creation varies but the surrounding workflow should remain stable and testable.
Factory Method: A creation hook that lets a class defer the choice of concrete product to subclasses or another controlled variation point.
Factory Method is valuable when you have a stable algorithm around an unstable creation decision. The goal is not to hide new for its own sake. The goal is to keep the workflow readable while allowing the created type to vary cleanly.
The classic version uses an abstract creator with a factory method that subclasses implement:
1interface Document {
2 void render();
3}
4
5final class PdfDocument implements Document {
6 @Override
7 public void render() {
8 System.out.println("Rendering PDF");
9 }
10}
11
12final class HtmlDocument implements Document {
13 @Override
14 public void render() {
15 System.out.println("Rendering HTML");
16 }
17}
18
19abstract class DocumentExporter {
20 public final void export() {
21 Document document = createDocument();
22 document.render();
23 }
24
25 protected abstract Document createDocument();
26}
27
28final class PdfExporter extends DocumentExporter {
29 @Override
30 protected Document createDocument() {
31 return new PdfDocument();
32 }
33}
The important part is the split: export() stays stable, while createDocument() varies.
This pattern is strongest when:
If the only variability is a single constructor choice with no broader template around it, a static factory or injected supplier may be simpler.
Modern Java code does not always need inheritance-heavy factory hierarchies. You can express the same idea with composition:
1import java.util.function.Supplier;
2
3final class DocumentExporter {
4 private final Supplier<Document> documentFactory;
5
6 DocumentExporter(Supplier<Document> documentFactory) {
7 this.documentFactory = documentFactory;
8 }
9
10 void export() {
11 Document document = documentFactory.get();
12 document.render();
13 }
14}
This still captures the Factory Method idea: the creation decision is separated from the stable workflow. It just uses composition rather than subclassing.
The first mistake is using Factory Method when a constructor or static factory would already be obvious.
The second mistake is pushing unrelated business branching into the factory method. Creation variation should stay about product selection, not become a dumping ground for policy logic.
The third mistake is tying the hierarchy so tightly to inheritance that every new variant requires touching too many classes.
When reviewing Factory Method usage in Java, ask:
Factory Method earns its place when it cleanly isolates creation variability. Otherwise it just becomes polite indirection.