The Factory and Abstract Factory design patterns are used to create objects without specifying the exact class of object that will be created. These patterns are part of the creational design patterns, which focus on object creation mechanisms. Below is a brief explanation and implementation of both patterns in C++.
The Factory pattern defines an interface for creating an object but allows subclasses to alter the type of objects that will be created.
#include <iostream>
#include <memory>
// Product interface
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() {}
};
// Concrete Products
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing a Circle." << std::endl;
}
};
class Square : public Shape {
public:
void draw() override {
std::cout << "Drawing a Square." << std::endl;
}
};
// Factory class
class ShapeFactory {
public:
static std::unique_ptr<Shape> createShape(const std::string &shapeType) {
if (shapeType == "Circle") {
return std::make_unique<Circle>();
} else if (shapeType == "Square") {
return std::make_unique<Square>();
}
return nullptr;
}
};
// Client code
int main() {
auto shape1 = ShapeFactory::createShape("Circle");
shape1->draw();
auto shape2 = ShapeFactory::createShape("Square");
shape2->draw();
return 0;
}
The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.
#include <iostream>
#include <memory>
// Abstract Factory interface
class GUIFactory {
public:
virtual std::unique_ptr<Button> createButton() = 0;
virtual std::unique_ptr<Checkbox> createCheckbox() = 0;
virtual ~GUIFactory() {}
};
// Abstract Product interfaces
class Button {
public:
virtual void paint() = 0;
virtual ~Button() {}
};
class Checkbox {
public:
virtual void paint() = 0;
virtual ~Checkbox() {}
};
// Concrete Products for Windows
class WindowsButton : public Button {
public:
void paint() override {
std::cout << "Rendering a Windows Button." << std::endl;
}
};
class WindowsCheckbox : public Checkbox {
public:
void paint() override {
std::cout << "Rendering a Windows Checkbox." << std::endl;
}
};
// Concrete Factory for Windows
class WindowsFactory : public GUIFactory {
public:
std::unique_ptr<Button> createButton() override {
return std::make_unique<WindowsButton>();
}
std::unique_ptr<Checkbox> createCheckbox() override {
return std::make_unique<WindowsCheckbox>();
}
};
// Client code
int main() {
std::unique_ptr<GUIFactory> factory = std::make_unique<WindowsFactory>();
auto button = factory->createButton();
auto checkbox = factory->createCheckbox();
button->paint();
checkbox->paint();
return 0;
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?