Skip to main content

Abstract Factory

What This Concept Is

Abstract Factory is a creational pattern that defines an interface for creating a family of related products without binding clients to concrete classes. The guarantee it sells is consistency: every product returned by one factory instance belongs to the same family and is known to work together.

The structure is:

  • an AbstractFactory interface with one method per product kind (createButton, createScrollBar, createWindow)
  • concrete factories (MacFactory, WindowsFactory) that each return products from their own family
  • client code that holds an AbstractFactory and asks it for products without caring about the concrete family

The problem it absorbs: the client needs several products that must match (a Mac button belongs with a Mac scroll bar, never a Windows one), and the choice of family is made once, high in the call stack.

Why It Matters Here

If Factory Method answers how does one method choose a product, Abstract Factory answers how do we keep an entire object graph in one consistent dialect. It is the canonical answer to cross-platform UI toolkits, multi-dialect database clients, and plugin ecosystems where mixing components from two families would be a correctness bug, not just a style issue.

It also has a sharp misuse story: if there is only one product kind or only one family, Abstract Factory is structural tax with no correctness win.

Concrete Example

interface UIFactory {
createButton(): Button;
createScrollBar(): ScrollBar;
}

class MacFactory implements UIFactory {
createButton() { return new MacButton(); }
createScrollBar() { return new MacScrollBar(); }
}

class WinFactory implements UIFactory {
createButton() { return new WinButton(); }
createScrollBar() { return new WinScrollBar(); }
}

function buildUI(ui: UIFactory) {
const btn = ui.createButton();
const bar = ui.createScrollBar();
// guaranteed to match because ui is one instance
}

const factory: UIFactory = isMac() ? new MacFactory() : new WinFactory();
buildUI(factory);

Structural sketch:

          +--------------+              +----------+
| UIFactory |<-------------| Client |
| createButton | +----------+
| createScroll |
+--------------+
^ ^
| |
+---------------+ +---------------+
| MacFactory | | WinFactory |
+---------------+ +---------------+
| | | |
v v v v
MacBtn MacScroll WinBtn WinScroll

One factory is chosen once; all resulting products come from the same family.

Common Confusion / Misconception

The most common confusion is Abstract Factory versus Factory Method:

  • Factory Method uses inheritance. A subclass overrides one method to pick one product.
  • Abstract Factory uses composition. A client holds a factory object with several related creation methods.

A subtler confusion is Abstract Factory versus Builder. Builder constructs one complex object step by step; Abstract Factory returns several simple objects that must be compatible.

How To Use It

  1. Identify a set of products that must agree (all Mac, all Windows; all SQL, all NoSQL).
  2. Define an interface naming one creation method per product kind.
  3. Write one concrete factory per family.
  4. Inject the factory at the composition root; never let business code choose the family.
  5. If a new product kind gets added, every factory must change. Accept that cost only if the product family really is fixed.

Check Yourself

  1. What correctness property does Abstract Factory protect that Factory Method does not?
  2. Why is adding a new product kind more painful than adding a new family?
  3. When is one enum plus a switch a better answer?

Mini Drill or Application

Design an Abstract Factory for cross-platform file dialogs with two families (desktop, mobile). Implement:

  1. the DialogFactory interface with createOpenDialog and createSaveDialog
  2. two concrete factories returning platform-appropriate dialogs
  3. a client function that takes the factory as a parameter and never checks the platform

Then delete the interface and rewrite it as one createDialogs(platform) function. Compare readability.

Read This Only If Stuck