Abstract Factory Pattern: Families of Related Objects
design-patternscreationalabstract-factory

Intent
Abstract Factory provides an interface for creating families of related objects without specifying their concrete classes. It guarantees that the products created are compatible with each other.
The Problem
Imagine a UI system that must support multiple themes. Each theme has buttons, inputs, and cards with consistent styles:
// Without pattern: dispersed theme logic
function createButton(theme: string) {
if (theme === 'light') return new LightButton();
if (theme === 'dark') return new DarkButton();
}
// What if someone mixes a LightButton with DarkInput?The Solution: Abstract Factory
classDiagram
class UIFactory {
<<interface>>
+createButton(): Button
+createInput(): Input
}
class LightThemeFactory {
+createButton(): LightButton
+createInput(): LightInput
}
class DarkThemeFactory {
+createButton(): DarkButton
+createInput(): DarkInput
}
UIFactory <|.. LightThemeFactory
UIFactory <|.. DarkThemeFactoryTypeScript Implementation
// Abstract products
interface Button {
render(): string;
}
interface Input {
render(): string;
}
// Abstract factory
interface UIFactory {
createButton(label: string): Button;
createInput(placeholder: string): Input;
}
// Concrete factory: Light Theme
class LightThemeFactory implements UIFactory {
createButton(label: string): Button {
return {
render: () => `<button class="bg-white text-gray-900">${label}</button>`,
};
}
createInput(placeholder: string): Input {
return {
render: () => `<input class="bg-white" placeholder="${placeholder}">`,
};
}
}
// Usage with dependency injection
class LoginForm {
constructor(private factory: UIFactory) {}
render(): string {
const emailInput = this.factory.createInput('Email');
const submitButton = this.factory.createButton('Login');
return `<form>${emailInput.render()}${submitButton.render()}</form>`;
}
}
// Client decides which factory to use
const factory = theme === 'dark' ? new DarkThemeFactory() : new LightThemeFactory();
const loginForm = new LoginForm(factory);When to Use
| Situation | Recommendation |
|---|---|
| Multiple themes/skins | ✅ Recommended |
| Cross-platform support | ✅ Recommended |
| Families of related products | ✅ Recommended |
| Single product without variants | ❌ Use Factory Method |
Conclusion
Abstract Factory guarantees consistency when creating families of related objects, avoiding incompatible combinations.