2. Factory Method
The Factory Method pattern defines an interface for creating objects but lets subclasses decide which class to instantiate. It defers instantiation to subclasses, promoting loose coupling between a creator and the products it produces.
Intent and Motivation
Intent: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Motivation: Direct new calls in client code tightly couple callers to concrete classes. When product types change or grow, every caller must be updated. Factory Method moves creation logic into a dedicated method (often overridden in subclasses), so clients depend only on the abstract product interface. New product types are added by creating new subclasses — no existing client code changes.
This pattern is the foundation of many frameworks: UI toolkits create platform-specific widgets; document editors create format-specific parsers — all through factory methods.
Structure (UML-like)
┌──────────────────┐ creates ┌──────────────────┐
│ Creator │ ─────────────────────► │ Product │ (interface)
├──────────────────┤ ├──────────────────┤
│ + factoryMethod()│ │ + operation() │
│ + someOperation()│ └────────▲─────────┘
└────────▲─────────┘ │
│ │
│ extends │ implements
┌────────┴─────────┐ ┌────────┴─────────┐
│ ConcreteCreatorA │ │ ConcreteProductA │
├──────────────────┤ ├──────────────────┤
│ + factoryMethod()│ ─── returns ─────────► │ + operation() │
└──────────────────┘ └──────────────────┘
Participants:
- Product — interface for objects the factory creates.
- ConcreteProduct — implements the Product interface.
- Creator — declares the factory method returning a Product.
- ConcreteCreator — overrides the factory method to return a ConcreteProduct.
Java Example
// Product
interface Notification {
void send(String message);
}
// Concrete Products
class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
// Creator
abstract class NotificationFactory {
public void notifyUser(String message) {
Notification notification = createNotification();
notification.send(message);
}
protected abstract Notification createNotification();
}
// Concrete Creators
class EmailFactory extends NotificationFactory {
protected Notification createNotification() {
return new EmailNotification();
}
}
class SMSFactory extends NotificationFactory {
protected Notification createNotification() {
return new SMSNotification();
}
}
// Usage
NotificationFactory factory = new EmailFactory();
factory.notifyUser("Your order shipped!");
JavaScript Example
class DocumentFactory {
createDocument(type) {
switch (type) {
case 'pdf': return new PDFDocument();
case 'word': return new WordDocument();
default: throw new Error(`Unknown type: ${type}`);
}
}
openAndSave(type, content) {
const doc = this.createDocument(type);
doc.open();
doc.write(content);
doc.save();
return doc;
}
}
class PDFDocument {
open() { console.log('Opening PDF'); }
write(content) { console.log('Writing to PDF:', content); }
save() { console.log('Saving PDF'); }
}
class WordDocument {
open() { console.log('Opening Word'); }
write(content) { console.log('Writing to Word:', content); }
save() { console.log('Saving Word'); }
}
const factory = new DocumentFactory();
factory.openAndSave('pdf', 'Hello World');
Subclasses can override createDocument in JavaScript by extending DocumentFactory for the classic Factory Method variant.
Real-World Use Cases
| Framework / System | Usage |
|---|---|
| java.util.Calendar | Calendar.getInstance() returns locale-specific calendar implementations. |
| java.nio.charset.Charset | forName() returns charset encoder/decoder factories. |
| Spring Framework | BeanFactory / ApplicationContext — getBean() is a factory method for dependency objects. |
| React | createElement() (internal) creates component instances based on type. |
| JUnit 5 | @Test methods are discovered and instantiated by the test engine factory. |
| javax.xml.parsers | DocumentBuilderFactory.newInstance() selects a platform parser implementation. |
Pros and Cons
| Pros | Cons |
|---|---|
| Decouples creators from concrete products | Can lead to many small subclasses (one per product type) |
| Follows Open/Closed Principle — extend without modifying | Adds indirection; simple cases may not need a factory |
| Single Responsibility — creation logic in one place | Subclass proliferation if product families grow large |
| Supports parallel class hierarchies (creator ↔ product) | Static factory methods blur the line with Simple Factory |
| Enables hooks in the creator’s template method | Runtime type selection may need parameterization beyond subclassing |
When to Use vs When NOT to Use
Use when:
- A class cannot anticipate the class of objects it must create.
- A class wants its subclasses to specify the objects it creates.
- You want to localize knowledge of which helper subclass is the delegate.
- The creation logic is complex or varies by environment (OS, locale, config).
Do NOT use when:
- Object creation is trivial and unlikely to change — a simple constructor suffices.
- You need to create families of related products (use Abstract Factory instead).
- You need step-by-step construction of complex objects (use Builder).
- A single parameterized factory (Simple Factory) is enough without subclass extension.
Common Mistakes
- Confusing Simple Factory with Factory Method — Simple Factory is a single function; Factory Method uses polymorphic subclassing.
- Returning concrete types from the factory method — callers should depend on the Product interface.
- Putting business logic inside the factory method — keep it focused on instantiation; delegate behavior to the product.
- Creating a new subclass for every minor variant — consider parameterized factories or registries when variants are data-driven.
- Ignoring dependency injection — in DI frameworks, bean factories often replace hand-rolled Factory Method hierarchies.
Related Patterns
- Abstract Factory — Factory Method creates one product; Abstract Factory creates families of related products.
- Template Method — Factory Method is often called within a Template Method’s algorithm steps.
- Prototype — alternative when cloning existing objects is cheaper than creating from scratch.
- Builder — constructs complex objects step by step; can be combined with Factory Method for final assembly.
- Singleton — factory classes are sometimes singletons to centralize creation.