Factory Method

The Factory Method pattern defines an interface for creating objects but lets subclasses alter the type of objects that will be created.

Intent

You have a creator class that needs to produce objects, but you don’t want to hard-code the exact class of those objects. Instead, you define a method that subclasses override to supply the concrete product.

Structure

  • Creator — declares the factory method, which returns a Product.
  • ConcreteCreator — overrides the factory method to return a ConcreteProduct.
  • Product — the interface for objects the factory method creates.

Example

interface Button {
  render(): void;
}

class WindowsButton implements Button {
  render() { console.log("Windows button"); }
}

class MacButton implements Button {
  render() { console.log("Mac button"); }
}

abstract class Dialog {
  abstract createButton(): Button;

  show() {
    const btn = this.createButton();
    btn.render();
  }
}

class WindowsDialog extends Dialog {
  createButton() { return new WindowsButton(); }
}

class MacDialog extends Dialog {
  createButton() { return new MacButton(); }
}

When to Use It

  • You don’t know ahead of time the exact types your code will need to work with.
  • You want to provide users of your library a way to extend its internal components.

Trade-Offs

AdvantageDisadvantage
Avoids tight coupling between creator and productsCan lead to many subclasses
Single Responsibility PrincipleRequires an inheritance hierarchy