Factory Method Pattern
Define an interface for creating an object — let subclasses decide which class to instantiate.
new ConcreteProduct() behind a method (often on an abstract Creator). Clients call the method; which concrete product gets built is decided by which Creator subclass you use — not by if chains in the client.Why It Matters
- Open/Closed — New product families extend by subclassing Creator, not editing callers.
- Single creation choke-point — Logging, quotas, feature flags wrap one factory method.
- Testing — Inject a test
Creatorthat returns stubs — no staticnewin domain logic.
In Layman's Terms
A pizza chain does not ask every customer to knead dough in the kitchen. Each franchise (concrete creator) knows how to make its local pizza (product) — the menu (client) just says "one pizza please".
Factory Method is that hook: something else owns the recipe for construction so your ordering code stays the same when you add Chicago vs NY style.
Real-World Analogy
🍕 Franchise kitchen
Corporate defines interface OrderPizza() and what happens after (box, slice). Each store implements how the actual pizza is constructed — deep dish vs thin crust.
Adding a new regional style means new subclass, not editing every kiosk's code.
Visual
class ReportApp {
void run(String format) {
Document doc;
if (format.equals("pdf")) doc = new PdfDocument();
else if (format.equals("html")) doc = new HtmlDocument();
// +markdown? change this file again
doc.render();
}
} abstract class ReportCreator {
abstract Document createDocument();
void export() { createDocument().render(); }
}
class PdfReportCreator extends ReportCreator {
Document createDocument() { return new PdfDocument(); }
} ┌──────────────┐ ┌──────────────┐
│ Creator │────────▶│ Product │◀──┐
├──────────────┤ creates└──────────────┘ │
│+ factoryM() │ ▲ │
│+ business() │ │ │
└──────┬───────┘ │ │
│ │ │
┌────┴────┐ ┌────┴─────┐ ┌─────┴──────┐
│Concrete │ │Concrete │ │ Concrete │
│Creator A│ │Product A │ │ Product B │
└─────────┘ └──────────┘ └────────────┘Top — central if/switch vs subclass-owned creation. Bottom — Creator/Product parallel hierarchies.
When to Use
- The exact type of product cannot be known until runtime or varies by deployment / plugin.
- Framework defines skeleton (template method); app supplies concrete products.
- You want parallel hierarchies — each product variant has a matching creator variant.
- You are tired of `new` sprinkled through UI/services — centralise construction.
When NOT to Use
- Only one concrete product exists forever — a plain constructor or DI
@Beanis enough. - You need families of related products together (PDF + Parser + Validator) — consider Abstract Factory.
- Object graphs are huge and step-built — Builder fits better.
Anti-Pattern (What NOT to Do)
public final class UiExporter {
public void saveAs(User user, String ext) {
Document doc;
switch (ext) {
case "pdf" -> doc = new PdfDocument(user);
case "docx" -> doc = new DocxDocument(user);
default -> throw new IllegalArgumentException(ext);
}
doc.write(Path.of("out." + ext));
}
}UiExporter and every caller path — tight coupling to concrete classes.The Right Way
public interface ExportCreator {
Document create(User user);
}
public final class PdfExportCreator implements ExportCreator {
public Document create(User user) { return new PdfDocument(user); }
}
public final class ExportDialog {
private final ExportCreator creator;
public ExportDialog(ExportCreator creator) { this.creator = creator; }
public void save(User user, Path out) {
creator.create(user).write(out); // stable — swap creator impl
}
}ExportCreator, not on PdfDocument. New format = new class implementing ExportCreator.Pros & Cons
- Decouples client from concrete product classes.
- Aligns with Template Method — Creator often implements algorithm skeleton.
- Natural fit for plugins — load Creator implementation per configuration.
- Two parallel hierarchies can feel heavy for small apps.
- Indirection — readers jump Creator → Product to understand wiring.
- Overkill when only one implementation exists.
Factory Method vs neighbours
| Aspect | Factory Method | Abstract Factory | Simple factory (idiom) |
|---|---|---|---|
| Scope | One product kind per Creator | Families of related products | One method + switch/registry |
| Extension | Subclass Creator | New concrete factory | Edit method or registry |
| GoF pattern? | Yes | Yes | No (idiom / helper) |
| Typical pain | Parallel hierarchies grow | Many interfaces at once | God method grows |
Common Confusions Cleared Up
Constructors only build their class. Factory Method returns a supertype and can hide subclasses, caching, pooling, or remote proxies.
Factory Method chooses which class to build in one shot. Builder assembles one complex object step-by-step with many optional parts.
Variations / Implementations
1️⃣ Classic GoF
Abstract factoryMethod() on Creator; each concrete Creator returns one Product type.
abstract class Dialog {
abstract Button createButton(); // factory method
void render() {
Button b = createButton();
b.paint();
}
}
class WinDialog extends Dialog {
Button createButton() { return new WinButton(); }
}Dialog) stays fixed; platform-specific button comes from subclass.2️⃣ Parameterized factory (simple factory)
One method takes a key — often not listed as a separate GoF pattern but common in apps.
Document create(String type, User u) {
return registry.get(type).apply(u); // Map<String, Function<User,Document>>
}3️⃣ Spring-style injection
@Bean methods are factory methods — container calls them to produce singleton/prototype beans.
@Configuration
class AppConfig {
@Bean
PaymentClient paymentClient(PaymentProps p) {
return PaymentClient.connect(p.getUrl());
}
}Common Mistakes / Anti-Patterns
- Naming every static
create()"factory method" — the pattern is about polymorphic creation, not static helpers alone. - God class with
createEverything(type)and 40-case switch. - Returning
nullfrom factory — prefer Optional or exception.
Interview Q&A
Likely Follow-up Questions
- Sketch Template Method + Factory Method together on a
DataExporter. - How does
Supplier<T>in Java 8 mirror Factory Method? - When does a parameterized factory violate Open/Closed?
- Compare Factory Method with Prototype pattern.
Quick Cheat Sheet
Creator.factoryMethod() → Product.switch (type) in UI layer.@Bean, Supplier, SPI services.