What It Is
The Abstract Factory pattern creates whole families of related objects that belong together. Where a factory method makes one product, an abstract factory makes a matching set — and guarantees the pieces are never mixed.
The classic case is theming: a light theme must produce light buttons and light labels, never a mix.
Example: A Theme Factory
renderScreen takes any UIFactory and builds a consistent screen from it. Swapping the whole look is one argument — and mixing themes is impossible by construction.
One factory, one consistent family
The light theme produces only light parts, the dark theme only dark ones. renderScreen never changes.
Output: PHP script
<?php
interface Button {
public function render(): string;
}
interface Label {
public function render(): string;
}
// The abstract factory makes a whole matching family.
interface UIFactory {
public function newButton(): Button;
public function newLabel(): Label;
}
class LightButton implements Button {
public function render(): string {
return "[ OK ] light button";
}
}
class LightLabel implements Label {
public function render(): string {
return "hello light label";
}
}
class DarkButton implements Button {
public function render(): string {
return "[ OK ] dark button";
}
}
class DarkLabel implements Label {
public function render(): string {
return "hello dark label";
}
}
class LightTheme implements UIFactory {
public function newButton(): Button {
return new LightButton();
}
public function newLabel(): Label {
return new LightLabel();
}
}
class DarkTheme implements UIFactory {
public function newButton(): Button {
return new DarkButton();
}
public function newLabel(): Label {
return new DarkLabel();
}
}
function renderScreen(UIFactory $f): void {
echo $f->newLabel()->render(), "\n";
echo $f->newButton()->render(), "\n";
}
renderScreen(new LightTheme());
renderScreen(new DarkTheme());
When to Use It
Use it when several objects must stay consistent with each other — themes, platform widget sets, matching import/export format pairs.
Skip it when the products do not need to match. Independent objects deserve independent constructors, not a family factory.
Pros and Cons
Pros: family consistency is guaranteed; whole families swap with one value; calling code depends only on interfaces.
Cons: a lot of interfaces and classes for a small job; adding a new product to the family means touching every factory.