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
| Advantage | Disadvantage |
|---|---|
| Avoids tight coupling between creator and products | Can lead to many subclasses |
| Single Responsibility Principle | Requires an inheritance hierarchy |