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 / ApplicationContextgetBean() 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

  1. Confusing Simple Factory with Factory Method — Simple Factory is a single function; Factory Method uses polymorphic subclassing.
  2. Returning concrete types from the factory method — callers should depend on the Product interface.
  3. Putting business logic inside the factory method — keep it focused on instantiation; delegate behavior to the product.
  4. Creating a new subclass for every minor variant — consider parameterized factories or registries when variants are data-driven.
  5. Ignoring dependency injection — in DI frameworks, bean factories often replace hand-rolled Factory Method hierarchies.
  • 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.