Skip to content

Abstract Factory Pattern - Create Families of Related Objects

Updated: at 12:00 AM

1. The Problem

Problem: Creating Related Objects That Must Work Together

Many systems need to create families of related objects that are designed to be used together.

Example:

Naive approach:

if platform == "windows":
    button = WindowsButton()
    checkbox = WindowsCheckbox()
elif platform == "mac":
    button = MacButton()
    checkbox = MacCheckbox()

Problems:

We need a way to create consistent object families without hard-coding concrete types.

2. The Abstract Factory Pattern: Encapsulate Object Families

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

Core idea:

Structure:

What you get:

Use Abstract Factory when:

3. Implementation: Abstract Factory in Python

Abstract products

from abc import ABC, abstractmethod

class Button(ABC):
    @abstractmethod
    def render(self) -> str:
        pass

class Checkbox(ABC):
    @abstractmethod
    def render(self) -> str:
        pass

Concrete products

class WindowsButton(Button):
    def render(self) -> str:
        return "Windows Button"

class MacButton(Button):
    def render(self) -> str:
        return "Mac Button"

class WindowsCheckbox(Checkbox):
    def render(self) -> str:
        return "Windows Checkbox"

class MacCheckbox(Checkbox):
    def render(self) -> str:
        return "Mac Checkbox"

Abstract factory

class UIFactory(ABC):
    @abstractmethod
    def create_button(self) -> Button:
        pass

    @abstractmethod
    def create_checkbox(self) -> Checkbox:
        pass

Concrete factories

class WindowsUIFactory(UIFactory):
    def create_button(self) -> Button:
        return WindowsButton()

    def create_checkbox(self) -> Checkbox:
        return WindowsCheckbox()

class MacUIFactory(UIFactory):
    def create_button(self) -> Button:
        return MacButton()

    def create_checkbox(self) -> Checkbox:
        return MacCheckbox()

Client code

class Application:
    def __init__(self, factory: UIFactory):
        self.button = factory.create_button()
        self.checkbox = factory.create_checkbox()

    def render(self):
        return [self.button.render(), self.checkbox.render()]

Runtime family swapping

app = Application(WindowsUIFactory())
app = Application(MacUIFactory())

Client code never changes. Only the factory does.

4. Abstract Factory vs Factory Method vs Strategy

Key distinction:

Mental shortcut:

5. When to Use Abstract Factory (and When Not To)

Use it when:

Avoid it when:

Common pitfalls: