Abstract Factory Pattern
The Abstract Factory pattern provides an interface for creating families of related objects without specifying their concrete classes. Use it when your system needs to be independent of how its products are created, especially when working with multiple product families.
Overview
The Abstract Factory pattern groups a set of related Factory Methods under one interface, so a single factory can produce a whole family of compatible products. The classic example is a cross-platform UI toolkit: a WindowsFactory produces WindowsButton + WindowsCheckbox, a MacFactory produces MacButton + MacCheckbox, and the rest of the app never knows which family it's using.
When to use it
- You need to produce families of related objects that must be used together (e.g., themed UI components).
- You want to enforce, at the type level, that products from different families are not mixed.
- The application should be able to switch entire product families with a single configuration change.
Example
interface Button { render(): void }
interface Checkbox { toggle(): void }
interface UIFactory {
createButton(): Button;
createCheckbox(): Checkbox;
}
class DarkButton implements Button { render() { console.log("dark btn"); } }
class DarkCheckbox implements Checkbox { toggle() { console.log("dark check"); } }
class DarkUIFactory implements UIFactory {
createButton() { return new DarkButton(); }
createCheckbox() { return new DarkCheckbox(); }
}
function renderApp(factory: UIFactory) {
factory.createButton().render();
factory.createCheckbox().toggle();
}Pros
- Guarantees that products from the same family are used together.
- Isolates concrete classes — clients only depend on abstract interfaces.
- Swapping families (theme, platform, environment) is a one-line change.
Cons
- Adding a new product to the family forces every factory to implement it.
- More classes and interfaces than a single Factory Method, so the upfront cost is real.
- Overkill when you only have one family or the families rarely change.