0/0
Design Patterns

Factory Method Pattern

Defer instantiation to subclasses β€” same client code, different concrete products via a polymorphic factoryMethod() call.

Explore Topics

🎯
Intent
Define an interface for creation β€” let subclasses decide which class to make.
🏭 Factory Method Workbench β€” same client, different products
// CLIENT CODE β€” does NOT change when you swap the creator
Logistics shop = new RoadLogistics();
shop.planDelivery("Chicago", 800);
Install a creator β†’ swap the concrete product
Dispatch trace Β· 6 steps
  1. 1
    Client
    Logistics shop = new RoadLogistics();
    Client chooses WHICH concrete creator to install.
  2. 2
    Client
    shop.planDelivery("Chicago", 800);
    Calls the workflow on the abstract Logistics type.
  3. 3
    Logistics
    Transport t = createTransport();
    Template method calls the factory method β€” polymorphic dispatch fires here.
  4. 4
    RoadLogistics β—€ overrides factoryMethod()
    return new Truck();
    RoadLogistics.createTransport() override returns a Truck.
  5. 5
    Logistics
    t.deliver("Chicago", 800);
    Back in the template method; uses the Product through its abstract type.
  6. 6
    Truck β—€ concrete product
    return "Truck rumbled 800 km by road to Chicago";
    Truck.deliver() β€” the concrete product's actual behavior.
Parallel hierarchies Β· creator ↔ product
Β« abstract Β»
Logistics
β–Ό
🚚RoadLogistics
🚒SeaLogistics
✈️AirLogistics
πŸš†RailLogistics
═══▢
β•΄β•΄β–Ά
β•΄β•΄β–Ά
β•΄β•΄β–Ά
Β« interface Β»
Transport
β–Ό
Truck
Ship
Plane
Train
Each concrete creator overrides createTransport() to return its product.
Add a new mode = add one Logistics subclass + one Transport class.
Console
> Truck rumbled 800 km by road to Chicago
Pick a creator above. Steps 4 and 6 (colored) are the polymorphic dispatches that change.
🎯
Intent
Define an interface for creation β€” let subclasses decide which class to make.

Factory Method is a creational pattern that hands the responsibility of creating products to a polymorphic operation in a Creator class. Instead of calling `new ConcreteProduct()` directly, client code calls `creator.factoryMethod()` β€” and the concrete Creator subclass at runtime decides which product to return. This is often summarized as a "virtual constructor" because the choice of which class to instantiate is deferred to subclasses, just like the choice of which override to call is deferred at runtime for any virtual method. Erich Gamma's broader maxim "the `new` operator considered harmful" applies here: hard-coded `new` calls couple client code to concrete classes, and Factory Method is the cheapest way to undo that coupling within a single product family.

Key Ideas
  • Replace direct `new ConcreteProduct()` calls with a polymorphic factoryMethod() call.
  • "Virtual constructor" β€” defer the choice of concrete product to a subclass override.
  • Client code depends only on the abstract Product type, never on concrete products.
  • Adding a new product = adding a new Creator+Product pair, NOT editing the client.
  • The Creator itself is the extension point β€” anyone can subclass it to plug in a new product.
Strengths
  • ✦Decouples client code from concrete product classes
  • ✦Encapsulates the construction decision in one place per Creator subclass
  • ✦Embodies Open/Closed Principle β€” extend by subclassing, no client edits
  • ✦Each Creator subclass has single responsibility for its product line
Weaknesses
  • β–³Requires inheritance β€” every product family means a new Creator subclass
  • β–³Subclass proliferation: trivial product variations multiply class count
  • β–³Indirection: readers must trace the polymorphic dispatch to know what gets built
  • β–³Overkill when the product set is small and unlikely to grow
Used in:The JDK uses Factory Method extensively. `Collection.iterator()` is a textbook example: every Collection implementation returns ITS OWN concrete Iterator subclass β€” ArrayList returns one type, HashSet another, LinkedList another β€” and client code only sees the abstract `Iterator` type.
Code Snippets

Quiz

Intent Quiz
QUIZ 1/6
Which statement best captures the GoF Intent of the Factory Method pattern?

Diagrams

UML Class Diagram β€” the GoF Factory Method structure
Loading diagram...
Parallel Hierarchies β€” Creator subtree mirrors Product subtree
Loading diagram...

Practice

Drag each class from the LogisticsApp into the GoF participant role it plays. Each role accepts exactly two classes.
EXERCISE 1/4
Logistics (abstract class with createTransport)
MowerStore (abstract class with createMower)
Transport (interface with deliver method)
Mower (interface with cut method)
RoadLogistics (overrides createTransport to return Truck)
GasMowerStore (overrides createMower to return GasMower)
Truck (implements Transport.deliver)
GasMower (implements Mower.cut)
Creator (abstract)
Product (interface)
Concrete Creator
Concrete Product
Spot the bug β€” why does this code defeat the Factory Method pattern?
EXERCISE 2/4
Click on the line you think contains the bug, then press Confirm.
1abstract class Logistics {
2 abstract Transport createTransport();
3
4 public void planDelivery(String dest, int km) {
5 Transport t = new Truck(); // <- look here
6 System.out.println("load onto " + t.getClass().getSimpleName());
7 System.out.println(t.deliver(dest, km));
8 }
9}
10
11class SeaLogistics extends Logistics {
12 @Override Transport createTransport() { return new Ship(); }
13}
14
15// caller:
16new SeaLogistics().planDelivery("Rotterdam", 4200);
17// Prints: "load onto Truck" <-- WRONG! SeaLogistics should produce Ship.
Order the 6 GoF implementation steps for refactoring direct-`new` to Factory Method
EXERCISE 3/4
Drag the lines into the correct order.
1. Declare a Product interface (or abstract class) that captures the operations every product must support.
2. Make every concrete product class implement that Product interface.
3. Introduce a Creator class with a factoryMethod() returning the Product type.
4. Replace every `new ConcreteProduct()` call site inside the Creator with a call to factoryMethod().
5. Add ConcreteCreator subclasses β€” one per product type β€” each overriding factoryMethod().
6. Make the base factoryMethod() abstract (or keep a default implementation if most subclasses share one product).
Factory Method myths and gotchas β€” true or false?
EXERCISE 4/4
A "factory method" must always be static.
The Creator's factoryMethod() MUST be abstract.
Factory Method is the same as Simple Factory.
Factory Method requires inheritance to work.
`Calendar.getInstance(Locale)` in the JDK is a GoF Factory Method.
Adding a new ConcreteProduct usually requires adding a new ConcreteCreator (parallel hierarchies).
Factory Method violates the Open/Closed Principle.

References

πŸ“š

Design Patterns: Elements of Reusable Object-Oriented Software β€” Factory Method chapter

en.wikipedia.org

book
πŸ“„

Refactoring.Guru β€” Factory Method (problem, structure, code in 9 languages)

refactoring.guru

article
πŸ“„

Wikipedia β€” Factory method pattern

en.wikipedia.org

article
πŸ“š

Effective Java β€” Item 1: Consider static factory methods instead of constructors (Joshua Bloch)

oreilly.com

book
πŸ“š

Head First Design Patterns β€” Factory Pattern chapter (Freeman & Robson)

oreilly.com

book