Last updated: Apr 29, 2026
Factory Method
A factory is a helper that creates the right kind of object for you so the rest of your code doesn’t need to know which concrete class to use. You tell the factory what you need, and it gives you back the right object. When you later need to support a new type, you update the factory — the calling code stays the same.
How It Works
There are two common forms:
Simple Factory
A single function or class with a create method that picks the right type based on input.
interface Notification {
send(message: string): void;
}
class EmailNotification implements Notification {
send(message: string) {
console.log(`Email: ${message}`);
}
}
class SMSNotification implements Notification {
send(message: string) {
console.log(`SMS: ${message}`);
}
}
class NotificationFactory {
static create(type: "email" | "sms"): Notification {
switch (type) {
case "email":
return new EmailNotification();
case "sms":
return new SMSNotification();
default:
throw new Error(`Unknown notification type: ${type}`);
}
}
}
const notification = NotificationFactory.create("email");
notification.send("Hello");
All creation logic lives in one place. When you add push notifications, you update the factory and nothing else.
Classic (GoF) Factory Method
The Gang of Four version is more formal: an abstract creator class declares a factory method, and each subclass overrides it to return a different product. This is less common in everyday code but worth knowing.
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();
}
}
Dialog doesn’t know or care which button it gets — each subclass decides. The trade-off is that you need a new subclass for every variant, which can pile up.
In JavaScript, Keep It Simple
In JS/TS a factory can be as simple as a function that returns an object:
const createUser = (firstName: string, lastName: string) => ({
id: crypto.randomUUID(),
createdAt: Date.now(),
firstName,
lastName,
fullName: `${firstName} ${lastName}`,
});
const user = createUser("John", "Doe");
Note: every call produces a brand-new object with its own copy of every property and method. If you’re creating many objects that share behavior, a classmay be more memory-efficient because methods live on the prototype and are shared across all instances instead of being duplicated.
When to Use It
- The exact type you need depends on runtime input (user config, environment, API response).
- You want to add new types without touching existing code — just update the factory.
- You want to hide complex creation logic so callers don’t need to know the details.
- You’re building a library and want users to extend or swap internal components.
Factory vs Strategy
Factory decides which object to create. Strategy decides which behavior to use after the object already exists.