Open In App

Factory Method Pattern | C++ Design Patterns

Factory Method Pattern provides an interface for creating objects but leaves the actual object instantiation to derived classes. This allows for flexibility in object creation and promotes loose coupling between the creator (client code) and the concrete products.

Real-World Example of the Factory Method in C++

Imagine you want to build different types of things, like toys. You have a general idea of how toys are made, but you want different people to make different kinds of toys

In simple terms, the Factory Method Pattern is like a recipe for making things, but it lets different chefs (subclasses) create their own unique versions of those things while sticking to the same basic cooking instructions (the Factory Method).

Core Components of the Factory Method Pattern in C++

Let's break down the key participants of the Factory Method Pattern:

1. Creator (Abstract Creator)

2. Concrete Creator:

3. Product(Abstract Product):

4. Concrete Product:

5. Client:

Implementation of the Factory Method Pattern in C++

Let's implement the Factory Method Pattern in C++ step by step, explaining each part in detail. In this example, we'll create a simple shape factory that produces different shapes (e.g., Circle and Square).

Step 1: Define the Abstract Product (Shape)

// Abstract product class
class Shape {
public:
    virtual void draw() = 0;
    virtual ~Shape() {} // Virtual destructor for polymorphism
};

Here, we've defined an abstract class Shape with a pure virtual function draw(). This class represents the abstract product that all concrete products must inherit from.

Step 2: Define Concrete Products (Circle and Square)

// Concrete product class - Circle
class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a Circle" << std::endl;
    }
};

// Concrete product class - Square
class Square : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a Square" << std::endl;
    }
};

Here, we have two concrete classes, Circle and Square, that inherits from the Shape abstract class. Each concrete product (Circle and Square) provides its implementation of the draw() method.

Step 3: Define the Abstract Creator

// Abstract creator class
class ShapeFactory {
public:
    virtual Shape* createShape() = 0;
    virtual ~ShapeFactory() {} // Virtual destructor for polymorphism
};

The abstract creator class, ShapeFactory, declare a pure virtual function createShape(), which will be implemented by concrete creators to create specific shapes.

Step 4: Define Concrete Creators (CircleFactory and Square Factory)

// Concrete creator class - CircleFactory
class CircleFactory : public ShapeFactory {
public:
    Shape* createShape() override {
        return new Circle();
    }
};

// Concrete creator class - SquareFactory
class SquareFactory : public ShapeFactory {
public:
    Shape* createShape() override {
        return new Square();
    }
};

In this step, we've created two concrete creator classes, CircleFactory and SquareFactory, which implement the createShape() method to create instances of Circle and Square, respectively.

Step 5: Client Code

Now, let's create a client to use the Factory Method Pattern:

int main() {
    ShapeFactory* circleFactory = new CircleFactory();
    ShapeFactory* squareFactory = new SquareFactory();

    Shape* circle = circleFactory->createShape();
    Shape* square = squareFactory->createShape();

    circle->draw(); // Output: Drawing a Circle
    square->draw(); // Output: Drawing a Square

    delete circleFactory;
    delete squareFactory;
    delete circle;
    delete square;

    return 0;
}

In this client code, we first create instances of the concrete creators (circleFactory and squareFactory) and then use them to create instances of concrete products (cirlce and square). Finally, we call the draw() method on these objects, which produces the expected output.

Below is the complete combined code for the Factory Method Pattern in C++:

// Abstract product class
#include <bits/stdc++.h>
class Shape {
public:
    virtual void draw() = 0;
    virtual ~Shape() {
    } // Virtual destructor for polymorphism
};
// Concrete product class - Circle
class Circle : public Shape {
public:
    void draw() override
    {
        std::cout << "Drawing a Circle" << std::endl;
    }
};

// Concrete product class - Square
class Square : public Shape {
public:
    void draw() override
    {
        std::cout << "Drawing a Square" << std::endl;
    }
};
// Abstract creator class
class ShapeFactory {
public:
    virtual Shape* createShape() = 0;
    virtual ~ShapeFactory() {
    } // Virtual destructor for polymorphism
};
// Concrete creator class - CircleFactory
class CircleFactory : public ShapeFactory {
public:
    Shape* createShape() override { return new Circle(); }
};

// Concrete creator class - SquareFactory
class SquareFactory : public ShapeFactory {
public:
    Shape* createShape() override { return new Square(); }
};
int main()
{
    ShapeFactory* circleFactory = new CircleFactory();
    ShapeFactory* squareFactory = new SquareFactory();

    Shape* circle = circleFactory->createShape();
    Shape* square = squareFactory->createShape();

    circle->draw(); // Output: Drawing a Circle
    square->draw(); // Output: Drawing a Square

    delete circleFactory;
    delete squareFactory;
    delete circle;
    delete square;
  
      // Client code based on user-input
  
      /* cout << "Enter shape type (circle or square): ";
    string shapeType;
    cin >> shapeType;

    ShapeFactory* shapeFactory = nullptr;
    if (shapeType == "circle") {
        shapeFactory = new CircleFactory();
    } else if (shapeType == "square") {
        shapeFactory = new SquareFactory();
    } else {
        cout << "Invalid shape type entered." << endl;
        return 1;
    }

    Shape* shape = shapeFactory->createShape();
    shape->draw();

    delete shapeFactory;
    delete shape; */

    return 0;
}

Output
Drawing a Circle
Drawing a Square




This implementation demonstrates the Factory Method Pattern, where:

Real-World Use Cases of the Factory Method Pattern in C++ Design Patterns

The Factory Method Pattern finds application in various real-wrold scenarios, such as:

  1. GUI Libraries: GUI frameworks often use this pattern for creating UI components like buttons, windows, and dialogs. Different operating systems may have different implementations for these components.
  2. Database Drivers: Database connectivity libraries may use the Factory Method Pattern to create specific database dirver objects depending on the type of database being used (e.g., MySQL, PostgreSQL).
  3. Game Development: In game development, this pattern is used to create different types of game objects, characters, or weapons.
  4. Plugin Systems: When building extensible software systems, the Factory Method Pattern can be used to create and manage plugin instances dynamically.

Advantages of the Factory Method Pattern in C++ Design Patterns

Disadvantages of the Factory Method Pattern in C++ Design Patterns

Conclusion

The Factory Method Pattern is a valuable tool in C++ for achieving flexible and extensible object creation mechanisms. By abstracting the creation process into separate factory methods, you can write more maintainable, modular and testable code. It is a fundamental patten to have in your arsenal when designing object-oriented systems, offering a solution to the often complex problem of object instantiation.

Article Tags :