Creational Kit

Abstract Factory

Abstract Factory groups the creation of several related objects behind one interface, so the objects a program builds always come from the same matching set.

Complexity
Popularity

Problem

A UI library needs to render buttons, checkboxes, and text fields that look native on Windows, macOS, and Linux. Each platform has its own widget classes, and a screen only looks right if every widget on it comes from the same platform's set - mixing a Windows-style button with a macOS-style checkbox breaks the illusion immediately.

If the screen-building code instantiates `WindowsButton`, `MacCheckbox`, and so on directly, two things go wrong. First, the code that assembles a screen is littered with `if (platform === 'mac')` branches wherever a widget is created. Second, nothing stops a careless call from grabbing a widget from the wrong platform's set - the compiler has no concept of "these classes belong together."

Solution

Give every product type in the family its own interface (`Button`, `Checkbox`) and write one implementation class per platform per product. Then introduce a factory interface with one creation method per product type - `createButton()`, `createCheckbox()` - and implement it once per platform: `WindowsFactory`, `MacFactory`, `LinuxFactory`. Each concrete factory only ever knows how to build its own platform's widgets, so it physically cannot hand out a mismatched pair.

The screen-assembly code receives a factory instance (chosen once, e.g., at startup, based on the detected OS) and calls its creation methods without ever naming a concrete widget class. Switching platforms means swapping which factory gets injected - nothing else in the code changes.

When to Use

  • Reach for it when a system must stay agnostic to which concrete family of products it works with, and that family is chosen at runtime or configuration time.
  • Reach for it when several related product types must always be used together as a matching set, and accidentally mixing variants would be a real bug.
  • Reach for it when you already have a Factory Method for one product and realize a second, third, and fourth related product need the same variant-based creation logic.

Real-World Examples

  • **Java AWT/Swing `UIManager`** - swapping the look-and-feel (Metal, Nimbus, or a platform-native one) swaps out an entire factory that produces matching buttons, scrollbars, and menus.
  • **`document.createElement` behind DOM implementations** - different rendering engines (jsdom vs. a real browser) act as interchangeable factories producing element objects that all satisfy the same DOM interfaces.
  • **Database driver packages in ORMs (e.g., TypeORM, Sequelize)** - selecting `postgres` vs. `mysql` in the config swaps in a whole family of dialect-specific connection, query, and transaction objects.