design·lab

Creational pattern

Abstract Factory

One factory produces a whole family of related objects — so the pieces always match, and swapping the family swaps everything at once.

✗ The problem

Widgets built by hand, families mixed by accident

The client calls new on concrete widgets directly. Nothing stops it from mixing a light button with a dark checkbox.

function renderForm(theme) {
  // scattered if/else, easy to mismatch:
  const btn = theme === 'dark'
    ? new DarkButton() : new LightButton();
  const chk = new LightCheckbox();  // ← oops, forgot theme!
}
A LightButton next to a DarkCheckbox — inconsistent UI, and theme logic scattered across every call site.
✓ The pattern

One factory interface, one matching family per theme

A UIFactory declares createButton() and createCheckbox(). Each concrete factory returns parts from the same family.

class UIFactory {
  createButton()    { /* abstract */ }
  createCheckbox()  { /* abstract */ }
}

class LightFactory extends UIFactory {
  createButton()   { return new LightButton(); }
  createCheckbox() { return new LightCheckbox(); }
}
class DarkFactory extends UIFactory {
  createButton()   { return new DarkButton(); }
  createCheckbox() { return new DarkCheckbox(); }
}
UIFactory
createButton() / createCheckbox()
LightFactory
DarkFactory
✓ See it live

Pick a theme — get a matching family

The client asks one factory for a button and a checkbox. Switch theme and the whole family swaps together — never a mismatched pair.

☀️ Light 🌙 Dark
Button
Submit
Checkbox
Remember me
LightFactory produced this family
✓ Takeaway

Guaranteed-matching families

  • Abstract Factory creates a whole family of related objects that are guaranteed to match.
  • Contrast with Factory Method: one product per call. Abstract Factory bundles several products into one coherent family.
  • Caution: adding a new product type (e.g. createSlider()) means editing every concrete factory.
🎯 Principle applied: Abstract Factory upholds Open/Closed (add a new theme = a new factory) and Dependency Inversion (the client depends on the UIFactory interface, never concrete widgets).