CreationalC++verifiedVerified
Abstract Factory Pattern in C++
Provides an interface for creating families of related objects without specifying their concrete classes.
How to Implement the Abstract Factory Pattern in C++
1Step 1: Define abstract product interfaces
class Button {
public:
virtual ~Button() = default;
virtual std::string render() const = 0;
};
class Checkbox {
public:
virtual ~Checkbox() = default;
virtual std::string render() const = 0;
};2Step 2: Define the abstract factory
class UIFactory {
public:
virtual ~UIFactory() = default;
virtual std::unique_ptr<Button> createButton() const = 0;
virtual std::unique_ptr<Checkbox> createCheckbox() const = 0;
};3Step 3: Concrete products for Light theme
class LightButton : public Button {
public:
std::string render() const override { return "[Light Button]"; }
};
class LightCheckbox : public Checkbox {
public:
std::string render() const override { return "[Light Checkbox]"; }
};4Step 4: Concrete products for Dark theme
class DarkButton : public Button {
public:
std::string render() const override { return "[Dark Button]"; }
};
class DarkCheckbox : public Checkbox {
public:
std::string render() const override { return "[Dark Checkbox]"; }
};5Step 5: Concrete factories
class LightThemeFactory : public UIFactory {
public:
std::unique_ptr<Button> createButton() const override {
return std::make_unique<LightButton>();
}
std::unique_ptr<Checkbox> createCheckbox() const override {
return std::make_unique<LightCheckbox>();
}
};
class DarkThemeFactory : public UIFactory {
public:
std::unique_ptr<Button> createButton() const override {
return std::make_unique<DarkButton>();
}
std::unique_ptr<Checkbox> createCheckbox() const override {
return std::make_unique<DarkCheckbox>();
}
};6Step 6: Client code uses only the factory interface
void buildUI(const UIFactory& factory) {
auto btn = factory.createButton();
auto chk = factory.createCheckbox();
std::cout << btn->render() << " " << chk->render() << "\n";
}
int main() {
LightThemeFactory lightFactory;
DarkThemeFactory darkFactory;
buildUI(lightFactory);
buildUI(darkFactory);
}#include <iostream>
#include <string>
#include <memory>
#include <map>
#include <functional>
#include <format>
#include <stdexcept>
#include <vector>
#include <concepts>
// [step] Define abstract product interfaces with concepts
class IButton {
public:
virtual ~IButton() = default;
virtual std::string render() const = 0;
virtual void onClick(std::function<void()> handler) = 0;
};
class ITextInput {
public:
virtual ~ITextInput() = default;
virtual std::string render() const = 0;
virtual void setValue(const std::string& value) = 0;
virtual std::string getValue() const = 0;
};
class IPanel {
public:
virtual ~IPanel() = default;
virtual std::string render() const = 0;
};
// [step] Define the abstract factory interface
class IUIFactory {
public:
virtual ~IUIFactory() = default;
virtual std::unique_ptr<IButton> createButton(const std::string& label) const = 0;
virtual std::unique_ptr<ITextInput> createTextInput(const std::string& placeholder) const = 0;
virtual std::unique_ptr<IPanel> createPanel(const std::string& title) const = 0;
virtual std::string themeName() const = 0;
};
// [step] Material theme concrete products
class MaterialButton : public IButton {
std::string label_;
std::function<void()> handler_;
public:
explicit MaterialButton(std::string label) : label_(std::move(label)) {}
std::string render() const override {
return std::format("<md-button>{}</md-button>", label_);
}
void onClick(std::function<void()> handler) override {
handler_ = std::move(handler);
}
};
class MaterialTextInput : public ITextInput {
std::string placeholder_, value_;
public:
explicit MaterialTextInput(std::string ph) : placeholder_(std::move(ph)) {}
std::string render() const override {
return std::format("<md-input placeholder='{}' value='{}'/>",
placeholder_, value_);
}
void setValue(const std::string& v) override { value_ = v; }
std::string getValue() const override { return value_; }
};
class MaterialPanel : public IPanel {
std::string title_;
public:
explicit MaterialPanel(std::string t) : title_(std::move(t)) {}
std::string render() const override {
return std::format("<md-card><h2>{}</h2></md-card>", title_);
}
};
class MaterialFactory : public IUIFactory {
public:
std::unique_ptr<IButton> createButton(const std::string& label) const override {
return std::make_unique<MaterialButton>(label);
}
std::unique_ptr<ITextInput> createTextInput(const std::string& ph) const override {
return std::make_unique<MaterialTextInput>(ph);
}
std::unique_ptr<IPanel> createPanel(const std::string& title) const override {
return std::make_unique<MaterialPanel>(title);
}
std::string themeName() const override { return "Material"; }
};
// [step] Bootstrap theme concrete products
class BootstrapButton : public IButton {
std::string label_;
std::function<void()> handler_;
public:
explicit BootstrapButton(std::string label) : label_(std::move(label)) {}
std::string render() const override {
return std::format("<button class='btn btn-primary'>{}</button>", label_);
}
void onClick(std::function<void()> handler) override {
handler_ = std::move(handler);
}
};
class BootstrapTextInput : public ITextInput {
std::string placeholder_, value_;
public:
explicit BootstrapTextInput(std::string ph) : placeholder_(std::move(ph)) {}
std::string render() const override {
return std::format("<input class='form-control' placeholder='{}' value='{}'/>",
placeholder_, value_);
}
void setValue(const std::string& v) override { value_ = v; }
std::string getValue() const override { return value_; }
};
class BootstrapPanel : public IPanel {
std::string title_;
public:
explicit BootstrapPanel(std::string t) : title_(std::move(t)) {}
std::string render() const override {
return std::format("<div class='card'><h5>{}</h5></div>", title_);
}
};
class BootstrapFactory : public IUIFactory {
public:
std::unique_ptr<IButton> createButton(const std::string& label) const override {
return std::make_unique<BootstrapButton>(label);
}
std::unique_ptr<ITextInput> createTextInput(const std::string& ph) const override {
return std::make_unique<BootstrapTextInput>(ph);
}
std::unique_ptr<IPanel> createPanel(const std::string& title) const override {
return std::make_unique<BootstrapPanel>(title);
}
std::string themeName() const override { return "Bootstrap"; }
};
// [step] Factory registry for runtime selection
class UIFactoryRegistry {
std::map<std::string, std::function<std::unique_ptr<IUIFactory>()>> factories_;
public:
void registerFactory(const std::string& name,
std::function<std::unique_ptr<IUIFactory>()> creator) {
factories_[name] = std::move(creator);
}
std::unique_ptr<IUIFactory> create(const std::string& name) const {
auto it = factories_.find(name);
if (it == factories_.end())
throw std::runtime_error(std::format("Unknown theme: '{}'", name));
return it->second();
}
};
// [step] Client code with runtime theme switching
int main() {
UIFactoryRegistry registry;
registry.registerFactory("material", [] { return std::make_unique<MaterialFactory>(); });
registry.registerFactory("bootstrap", [] { return std::make_unique<BootstrapFactory>(); });
for (const auto& theme : {"material", "bootstrap"}) {
auto factory = registry.create(theme);
auto btn = factory->createButton("Submit");
auto input = factory->createTextInput("Enter name");
auto panel = factory->createPanel("Login");
std::cout << std::format("[{}] {}\n", factory->themeName(), btn->render());
std::cout << std::format("[{}] {}\n", factory->themeName(), input->render());
std::cout << std::format("[{}] {}\n", factory->themeName(), panel->render());
}
}Abstract Factory Pattern Architecture
hourglass_empty
Rendering diagram...
lightbulb
Abstract Factory Pattern in the Real World
“Imagine furnishing a room from IKEA versus a luxury boutique. Each store (factory) produces a complete set of furniture — chairs, tables, sofas — that share a consistent style. You pick the store, and every piece you get matches. You never mix a rustic IKEA chair with a baroque boutique table.”