Back to All Design Patterns
Pattern 1 of 22
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 dynamicallyInteractive Factory Method SimulatorLIVE PLAYGROUND
Interact with the controls below to see how this design pattern executes in memory at runtime.
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
| Participant | Role & Responsibility | Type |
|---|---|---|
| Transport (Interface) | Common product interface with deliver() | interface |
| Truck / Ship (Concrete) | Concrete implementations of Transport | class |
| Logistics (Creator) | Declares factory method createTransport() | class |
| RoadLogistics / SeaLogistics | Overrides factory method to return Truck or Ship | class |
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.