Factory Pattern Implementations

Factory Pattern Implementations

Creational Patterns in C++

The Factory Pattern is a creational design pattern that provides an interface for creating objects without specifying the class of the objects that will be created. It decouples the client code from the instantiation logic, promoting flexibility and maintainability. In C++, this pattern is often implemented using classes and templates to encapsulate the creation process.

Overview of the Factory Pattern

The Factory Pattern consists of three primary components:

  1. Factory Interface: A virtual function or abstract class that defines the method for creating objects.
  2. Factory Implementation: A concrete class that implements the factory interface, returning instances of specific product classes.
  3. Product Class: The class that represents the object being created, with methods for its operations.

The pattern abstracts the creation process, allowing clients to request objects without knowing their specific types. This reduces coupling between the client and the instantiation logic.

Components of the Factory Pattern

  • Simple Factory: A single method that returns a product based on input parameters.
  • Abstract Factory: A factory of factories, allowing clients to create families of products.
  • Factory Method: A method that returns an object, typically abstract, to be implemented by subclasses.

In C++, these components are often implemented using classes and templates. For example, a simple factory might look like this:

class Product {
public:
    virtual ~Product() = 0;
    virtual void display() = 0;
};

class ConcreteProductA : public Product {
public:
    void display() override {
        std::cout << "Concrete Product A" << std::endl;
    }
};

class ConcreteProductB : public Product {
public:
    void display() override {
        std::cout << "Concrete Product B" << std::endl;
    }
};

class Factory {
public:
    static Product* createProduct(int type) {
        if (type == 1) return new ConcreteProductA();
        else if (type == 2) return new ConcreteProductB();
        return nullptr;
    }
};

Implementation in C++

The Factory Pattern is commonly implemented using classes and templates to encapsulate the creation logic. A simple factory might be implemented as a static method in a class, while abstract factories use interfaces to define the creation process.

Simple Factory

A simple factory is a single method that returns a product based on input parameters. For example, a factory for game engines:

class GameEngine {
public:
    static GameEngine* createEngine(int type) {
        if (type == 1) return new GameEngineClassic();
        else if (type == 2) return new GameEngineModern();
        return nullptr;
    }
};

class GameEngineClassic {
public:
    void run() {
        std::cout << "Running Classic Game Engine" << std::endl;
    }
};

class GameEngineModern {
public:
    void run() {
        std::cout << "Running Modern Game Engine" << std::endl;
    }
};

Clients use the factory to request objects without knowing their specific types:

int main() {
    GameEngine* engine = GameEngine::createEngine(1);
    engine->run();
    return 0;
}

Abstract Factory

An abstract factory is a factory of factories, allowing clients to create families of products. It involves an abstract interface for the factory and a concrete implementation that returns instances of product classes.

class Product {
public:
    virtual ~Product() = 0;
    virtual void display() = 0;
};

class ConcreteProductA : public Product {
public:
    void display() override {
        std::cout << "Concrete Product A" << std::endl;
    }
};

class ConcreteProductB : public Product {
public:
    void display() override {
        std::cout << "Concrete Product B" << std::endl;
    }
};

class AbstractFactory {
public:
    virtual Product* createProductA() = 0;
    virtual Product* createProductB() = 0;
    virtual ~AbstractFactory() = 0;
};

class ConcreteFactory : public AbstractFactory {
public:
    Product* createProductA() override {
        return new ConcreteProductA();
    }

    Product* createProductB() override {
        return new ConcreteProductB();
    }
};

Examples

The Factory Pattern is often used in scenarios where objects need to be created dynamically or in a family of related classes. For instance, in a game engine, a factory might create different game types (e.g., classic, modern) based on user input.

Benefits

  • Encapsulation: The creation logic is encapsulated within the factory, reducing coupling between the client and the instantiation process.
  • Flexibility: Clients can request different product types without modifying the code.
  • Maintainability: Adding new product classes is easier than modifying existing code.

Conclusion

The Factory Pattern is a powerful creational design pattern in C++ that promotes flexibility, maintainability, and decoupling. By abstracting the creation process, it allows clients to request objects without knowing their specific types, making the codebase more robust and scalable. Implementing the pattern with simple factories, abstract factories, or factory methods provides a flexible solution for managing object creation in C++ applications.