2026/02/03 / Coding

GoF Design Patterns - Abstract Factory

A practical guide to the Abstract Factory pattern from the GoF collection: concept, when to use it, a C++ implementation example, caveats, and references.

Coding DesignPattern

Hello! I'm Pan-kun.

This entry covers the Abstract Factory pattern from the GoF (Gang of Four) design patterns.
I'll give a practical explanation including sample code (C++), how to build it, when to use it, caveats, and references.

Introduction

The Abstract Factory is a pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes.

As a primary reference, here's the Wikipedia definition:

"Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
https://en.wikipedia.org/wiki/Abstract_factory_pattern

"Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."
(Source: https://en.wikipedia.org/wiki/Abstract_factory_pattern)

As the definitions indicate, this pattern allows the client to work only with abstract interfaces and remain unaware of which concrete products are being created. By swapping implementations, you can replace an entire theme (family of products) consistently.

When to use it

Here are some typical scenarios where you might consider using Abstract Factory:

  • When you want to switch UI themes or platform-dependent UI components as a group.
  • When you need to create a set of products that must be consistent with each other (for example, switching pairs like Button and Checkbox).
  • When implementations must be swappable at runtime or through configuration.

Alternatives and considerations:

  • For simple cases, a Simple Factory (conditional creation) may be sufficient.
  • If you need to vary only a single product, Factory Method might be more appropriate.
  • Combining Abstract Factory with dependency injection (DI) improves testability.

Structure (Elements)

  • AbstractFactory: the factory interface for creating product families.
  • ConcreteFactory: implements the abstract factory and creates concrete products.
  • AbstractProductA, AbstractProductB: abstract product interfaces.
  • ConcreteProductA1, ConcreteProductB1: concrete product implementations.
  • Client: obtains products from the abstract factory and uses them via abstract interfaces.

A UML diagram is omitted here, but the above components form the basic structure.

C++ Implementation Example

Below is a concise C++ sample implementing an Abstract Factory for a Button / Checkbox product family.

C++
// AbstractFactory C++
#include <memory>
#include <iostream>
#include <string>

// Abstract Product A: Button
struct Button {
    virtual ~Button() = default;
    virtual std::string render() const = 0;
};

// Abstract Product B: Checkbox
struct Checkbox {
    virtual ~Checkbox() = default;
    virtual std::string render() const = 0;
};

// Concrete product family 1: Windows
struct WindowsButton : Button {
    std::string render() const override { return "WindowsButton"; }
};
struct WindowsCheckbox : Checkbox {
    std::string render() const override { return "WindowsCheckbox"; }
};

// Concrete product family 2: Mac
struct MacButton : Button {
    std::string render() const override { return "MacButton"; }
};
struct MacCheckbox : Checkbox {
    std::string render() const override { return "MacCheckbox"; }
};

// Abstract Factory
struct GUIFactory {
    virtual ~GUIFactory() = default;
    virtual std::unique_ptr<Button> createButton() const = 0;
    virtual std::unique_ptr<Checkbox> createCheckbox() const = 0;
};

// Concrete Factory: Windows
struct WindowsFactory : GUIFactory {
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<WindowsButton>();
    }
    std::unique_ptr<Checkbox> createCheckbox() const override {
        return std::make_unique<WindowsCheckbox>();
    }
};

// Concrete Factory: Mac
struct MacFactory : GUIFactory {
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<MacButton>();
    }
    std::unique_ptr<Checkbox> createCheckbox() const override {
        return std::make_unique<MacCheckbox>();
    }
};

// Client depends on GUIFactory (depends on abstraction)
void renderUI(const GUIFactory& factory) {
    auto btn = factory.createButton();
    auto chk = factory.createCheckbox();
    std::cout << "Render: " << btn->render() << ", " << chk->render() << "\n";
}

int main() {
    WindowsFactory wf;
    MacFactory mf;

    renderUI(wf); // Render: WindowsButton, WindowsCheckbox
    renderUI(mf); // Render: MacButton, MacCheckbox

    return 0;
}

Key points from the sample:

  • renderUI does not know concrete classes; it just uses products provided by GUIFactory.
  • Adding a new theme (product family) does not require changes to renderUI.

Advantages / Disadvantages

Advantages

  • You can create families of products consistently, making implementation swaps straightforward.
  • Clients are decoupled from concrete classes, improving portability and testability.
  • Introducing a new product family typically requires minimal changes to client code.

Disadvantages

  • Adding a new product type (a new AbstractProduct interface) requires modifying every ConcreteFactory, which can be costly.
  • If you pick the wrong abstraction granularity early, you may over-engineer and increase complexity.
  • Swapping implementations can affect serialization, APIs, and data formats, which may introduce compatibility issues.

Conclusion

The Abstract Factory is a powerful pattern when you need to swap related product families as a whole.
Before adopting it, evaluate the scope of products to be added, your test strategy, and the impact on APIs/serialization.
Combining it with dependency injection improves testability and flexibility. Start small and extend abstractions as needed to avoid premature over-engineering.

References:

Abstract factory pattern - Wikipediaen.wikipedia.orgAbstract factory pattern - Wikipedia

I'll cover another GoF pattern next time. The code samples shown here are simplified for learning purposes — review and adapt them to your production requirements before use.

Thanks for reading — Pan-kun!

← GoF Design Pa…← Back to Blog