Create objects through a factory method instead of creating them directly with new in client code.
Factory helps you hide object-creation logic and return objects via a common interface.
flowchart TD
Client["Client"]
Factory["ShapeFactory"]
Product["Shape (Interface)"]
Circle["Circle"]
Rectangle["Rectangle"]
Client -->|"1. Request type"| Factory
Factory -->|"2. createShape(type)"| Product
Circle -->|implements| Product
Rectangle -->|implements| Product
style Client fill:#4CAF50,color:#fff
style Factory fill:#9C27B0,color:#fff
style Product fill:#2196F3,color:#fff
style Circle fill:#00BCD4,color:#fff
style Rectangle fill:#00BCD4,color:#fff
When client code directly creates objects:
- It depends on concrete classes.
- It needs
if/elseorswitchin many places. - Adding a new type requires updates in multiple files.
Move creation logic into one place (ShapeFactory).
Client asks the factory for an object by type, and factory returns std::unique_ptr<Shape>.
| Component | Role |
|---|---|
| Product | Common interface/base class (e.g., Shape) |
| Concrete Products | Actual implementations (e.g., Circle, Rectangle) |
| Factory | Decides and creates the correct concrete object |
| Client | Uses product interface, not concrete classes |
#include <iostream>
#include <memory>
#include <string>
class Shape {
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
class Circle : public Shape {
public:
void draw() const override { std::cout << "Drawing Circle\n"; }
};
class Rectangle : public Shape {
public:
void draw() const override { std::cout << "Drawing Rectangle\n"; }
};
class ShapeFactory {
public:
static std::unique_ptr<Shape> createShape(const std::string& type) {
if (type == "circle") return std::make_unique<Circle>();
if (type == "rectangle") return std::make_unique<Rectangle>();
return nullptr;
}
};
int main() {
auto shape = ShapeFactory::createShape("circle");
if (shape) shape->draw();
}- Object creation logic is repeated in many places.
- Client should not know concrete class names.
- You expect new product types in the future.
- Loose coupling: Client depends on interface, not concrete class.
- Single creation point: Easier maintenance.
- Extensible design: New products can be added with minimal client changes.
- Adds one more abstraction layer.
- Simple projects may not need it.
- If factory becomes too large, split into multiple factories.
- Factory: Chooses and creates which object to return.
- Builder: Controls how an object is built step-by-step.
"Factory pattern centralizes object creation and returns objects through a common interface, reducing client-side coupling."
Q: What changes when a new product is added?
Add a new concrete class and update factory creation logic. Client code usually remains unchanged.
If your code has many new ConcreteType(...) decisions spread across modules, consider Factory.