Coding · Design patterns
Factory Method pattern explained with examples
Short answer
Factory Method is a creational design pattern that defines a method for creating an object but lets subclasses decide which concrete class to instantiate. The base class writes its logic against a product interface and calls the factory method, such as createTransport(), instead of new. This lets you add new product types by adding a subclass, without editing the code that uses the products.
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. It is one of the five creational patterns in the Gang of Four (GoF) book, and the only creational one that is class-scoped, because it relies on inheritance.
The problem it solves
Imagine a notification module. It formats a message, sends it, and logs the result. At first it only sends email, so the code calls new EmailChannel() directly. Then the product needs SMS, then push notifications. Every new channel means editing the same class and adding another if branch, even though the formatting and logging steps never change.
The sending workflow is stable; only the kind of channel varies. Factory Method moves the one varying decision, which class to create, into a single overridable method.
Structure and participants
| Participant | Responsibility | In the example |
|---|---|---|
| Product | Interface of the objects the factory method creates. | Channel |
| ConcreteProduct | Implements the Product interface. | EmailChannel, SmsChannel |
| Creator | Declares the factory method and contains logic that uses the product. | Notifier |
| ConcreteCreator | Overrides the factory method to return a specific ConcreteProduct. | EmailNotifier, SmsNotifier |
TypeScript implementation
interface Channel {
send(to: string, text: string): string;
}
class EmailChannel implements Channel {
send(to: string, text: string): string { return `email to ${to}: ${text}`; }
}
class SmsChannel implements Channel {
send(to: string, text: string): string { return `sms to ${to}: ${text.slice(0, 20)}`; }
}
abstract class Notifier {
// The factory method: subclasses choose the concrete product.
protected abstract createChannel(): Channel;
// Shared logic that works with any Channel.
notify(to: string, text: string): void {
const channel = this.createChannel();
const result = channel.send(to, text.trim());
console.log("[log]", result);
}
}
class EmailNotifier extends Notifier {
protected createChannel(): Channel { return new EmailChannel(); }
}
class SmsNotifier extends Notifier {
protected createChannel(): Channel { return new SmsChannel(); }
}
const notifiers: Notifier[] = [new EmailNotifier(), new SmsNotifier()];
for (const n of notifiers) n.notify("ada", " Your order has shipped today ");
// [log] email to ada: Your order has shipped today
// [log] sms to ada: Your order has shippAdding push notifications now means writing PushChannel and PushNotifier. The notify method, and every caller of it, stays unchanged.
Before applying the pattern, the creation decision was buried in the shared logic:
class Notifier {
constructor(private kind: "email" | "sms") {}
notify(to: string, text: string): void {
// every new channel edits this method
const result = this.kind === "email"
? `email to ${to}: ${text}`
: `sms to ${to}: ${text.slice(0, 20)}`;
console.log("[log]", result);
}
}A lighter alternative: pass a factory function
Factory Method uses inheritance. In TypeScript you often get the same flexibility with composition by passing a creation function into the constructor. This avoids one subclass per product:
interface Channel { send(to: string, text: string): string; }
class Notifier {
constructor(private createChannel: () => Channel) {}
notify(to: string, text: string): void {
console.log("[log]", this.createChannel().send(to, text));
}
}
const push = new Notifier(() => ({ send: (to, text) => `push to ${to}: ${text}` }));
push.notify("ada", "Hello"); // [log] push to ada: HelloUse the subclass version when each creator already has its own class for other reasons, or when a framework expects you to extend a base class. Use the function version when the only difference between variants is the object they create.
When to use it, and when not to
Use Factory Method when:
- A class contains a stable algorithm but cannot know in advance which concrete objects it must create.
- You write a framework or library and want users to plug in their own product classes by subclassing.
- You want to keep creation logic for a type in one place instead of scattering
newcalls.
Avoid it when:
- There is only one product type and no real sign of a second one. A direct
newis clearer. - The only reason is to make testing possible. Passing the dependency in through the constructor is simpler.
- You would create a parallel hierarchy of creators that mirrors the products one to one with no other logic.
Real-world uses
- Java collections:
Iterable.iterator()is declared once, and each collection class (ArrayList,HashSetand others) overrides it to return its own iterator class. The GoF book describes this use of Factory Method for polymorphic iteration. - JavaScript iterables: every iterable implements
[Symbol.iterator](), a method that returns a new iterator suited to that collection. - UI frameworks often let subclasses override a method that creates a component, a cell or a view, while the base class controls layout and life cycle.
Related patterns
| Pattern | How it differs |
|---|---|
| Abstract Factory | Creates a whole family of related products through an object with several creation methods. Its methods are often implemented as factory methods. |
| Template Method | Factory Method is frequently called from a template method, as notify calls createChannel above. |
| Prototype | Creates objects by copying an instance instead of subclassing the creator, so it needs no parallel creator hierarchy. |
| Builder | Focuses on constructing one complex object step by step, not on choosing which class to create. |
FAQ
What is the difference between Factory Method and Abstract Factory?
Factory Method is a single method that subclasses override to create one product. Abstract Factory is an object with several creation methods that produce a family of related products that must be used together.
Is a simple factory function the same as Factory Method?
Not exactly. A function like createShape(kind) with a switch inside is often called a simple factory. The GoF Factory Method relies on a subclass overriding the creation method, but both hide new from the client.
Does Factory Method follow the open/closed principle?
Yes. You add a new product by adding a new product class and a new creator subclass, without changing the creator's existing logic.
Must the factory method be abstract?
No. The base class can provide a default implementation that returns a standard product, and subclasses override it only when they need something different.