Creational PatternBEGINNER7 min deep dive

Factory Method Pattern

Defines an interface for creating an object, but lets subclasses decide which class to instantiate.

Real-World Mental Model / Metaphor:

A logistics company dispatch center: the core logistics system asks for a 'Transport', while sub-departments dispatch Trucks, Ships, or Planes depending on terrain.

Interactive Runtime Simulator

Test and tweak inputs dynamically

Interactive Factory Method SimulatorLIVE PLAYGROUND

Interact with the controls below to see how this design pattern executes in memory at runtime.

Category: Creational
Switch Target Factory Platform:
The client code only interacts with GUIFactory.createButton() and GUIFactory.createCheckbox(). It never couples directly to concrete classes!
CONCRETE PRODUCTS CREATEDmac
Rendered Button:Rendered Checkbox:
The Problem It Solves

Coupling client code directly to concrete classes. If you instantiate `new Truck()` everywhere, adding `Ship` requires modifying every single callsite.

The Architectural Solution

Define a creator factory method. Concrete creators override this method to return specific implementations of the product interface.

Pattern Structure & Participants

ParticipantRole & ResponsibilityType
Transport (Interface)Common product interface with deliver()interface
Truck / Ship (Concrete)Concrete implementations of Transportclass
Logistics (Creator)Declares factory method createTransport()class
RoadLogistics / SeaLogisticsOverrides factory method to return Truck or Shipclass
Collaboration Rules:
  • Logistics defines createTransport()
  • RoadLogistics returns new Truck()
  • Client calls logistics.planDelivery() without knowing the transport vehicle

Production Code Implementation

Factory Method.java
// 1. Product Interface
public interface Transport {
    String deliver();
}

// 2. Concrete Products
public class Truck implements Transport {
    @Override
    public String deliver() {
        return "Delivering cargo by land in heavy box truck (ETA: 4h)";
    }
}

public class Ship implements Transport {
    @Override
    public String deliver() {
        return "Delivering shipping container across sea route (ETA: 48h)";
    }
}

// 3. Creator
public abstract class Logistics {
    // The Factory Method
    public abstract Transport createTransport();

    public String planDelivery() {
        Transport transport = createTransport();
        return "Logistics Dispatch: " + transport.deliver();
    }
}

// 4. Concrete Creators
public class RoadLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Truck();
    }
}

public class SeaLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Ship();
    }
}
When to Use:
  • •When you do not know beforehand the exact types and dependencies of objects your code should work with.
  • •When you want to provide users of your library or framework with a way to extend its internal components.
  • •When you want to save system resources by reusing existing objects instead of rebuilding them each time.
When to Avoid (Anti-Pattern):
  • •When the creation logic is trivial and will never change (simple `new` is fine).
  • •When you have only one concrete product and no anticipated variants.

Staff Engineering Interview Insights & Gotchas

  • Contrast Factory Method with Abstract Factory: Factory Method creates a single product; Abstract Factory creates families of related products.
  • Mention Spring's `@Bean` methods as modern real-world examples of Factory Methods.