C++ Factory Pattern - C++ Programming Tutorial
C++ Course / Design Patterns / C++ Factory Pattern

C++ Factory Pattern

BLUF: Mastering C++ Factory Pattern is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: C++ Factory Pattern

C++ is renowned for its efficiency. Learn how C++ Factory Pattern enables low-level control and high-performance computing in the tutorial below.

The Factory Pattern is a design technique frequently applied in object-oriented programming to instantiate objects while concealing the creation process from the client. Essentially, this pattern defines a method for generating objects within a parent class, enabling child classes to customize the specific type of objects generated.

C++ serves as a programming language focused on object-oriented principles and facilitates the Factory Pattern through the utilization of polymorphism and abstract classes. In order to apply the Factory Pattern within C++, the initial step involves establishing an abstract base class that outlines the shared interface for all objects producible by the factory. This foundational abstract base class is commonly referred to as the "Product" interface.

Explanation

Let's consider a demonstration of a basic program that generates various kinds of creatures. We can establish our abstract base class "Animal" in the following manner:

Example

class Animal {
public:
    virtual void makeSound() = 0;
    virtual ~Animal() {}
};

The "Animal" class serves as an abstract base class, establishing a shared interface for various animal types. This interface primarily revolves around a singular method named "makeSound". This method is designated as pure virtual, indicating that it lacks an implementation in the base class and necessitates implementation by its derived classes. Additionally, the destructor is virtual, guaranteeing proper destruction of derived class objects when deleted through a base class pointer.

Next, we have the option to generate various animal variations by developing concrete classes that adhere to the "Animal" interface. To illustrate, we will design two concrete classes: "Cat" and "Dog":

Example

class Cat : public Animal {
public:
    void makeSound() {
        std::cout << "Meow!" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() {
        std::cout << "Woof!" << std::endl;
    }
};

Both the classes "Cat" and "Dog" are derived from the "Animal" class and define the "makeSound" function.

Now, we are able to establish our factory class, which holds the responsibility of generating instances of the "Animal" category. This factory class must possess the capability to construct instances of any category that is derived from the "Animal" class.

Example

class AnimalFactory {
public:
    virtual Animal* createAnimal() = 0;
    virtual ~AnimalFactory() {}
};

The base class "AnimalFactory" serves as an abstract class outlining the structure for generating instances of the "Animal" class. This structure includes a solitary function named "createAnimal" that yields a reference to an "Animal" instance. The function is defined as a pure virtual method, signifying that it lacks an implementation in the base class and necessitates implementation in its derived classes.

Now, we have the ability to develop specific factory classes that adhere to the "AnimalFactory" interface and produce instances of various animal types. For instance, we will establish two distinct factory classes: "CatFactory" and "DogFactory":

Example

class CatFactory : public AnimalFactory {
public:
    Animal* createAnimal() {
        return new Cat();
    }
};

class DogFactory : public AnimalFactory {
public:
    Animal* createAnimal() {
        return new Dog();
    }
};

Both the classes "CatFactory" and "DogFactory" are derived from the base class "AnimalFactory" and define the "createAnimal" function. This function is responsible for instantiating a new object of the corresponding type ("Cat" or "Dog") and then providing a pointer to the base class "Animal".

The complete code is:

Example

#include <iostream>

class Animal {
public:
    virtual void makeSound() = 0;
    virtual ~Animal() {}
};

class Cat : public Animal {
public:
    void makeSound() {
        std::cout << "Meow!" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() {
        std::cout << "Woof!" << std::endl;
    }
};

class AnimalFactory {
public:
    virtual Animal* createAnimal() = 0;
    virtual ~AnimalFactory() {}
};

class CatFactory : public AnimalFactory {
public:
    Animal* createAnimal() {
        return new Cat();
    }
};

class DogFactory : public AnimalFactory {
public:
    Animal* createAnimal() {
        return new Dog();
    }
};
class AnimalClient {
public:
   
AnimalClient(AnimalFactory* factory) {
        animal_ = factory->createAnimal();
    }

    void makeAnimalSound() {
       
animal_->makeSound();
    }

    ~AnimalClient() {
        delete animal_;
    }

private:
    Animal* animal_;
};

int main() {

    AnimalFactory* catFactory = new CatFactory();
    AnimalClient* catClient = new AnimalClient(catFactory);
   
catClient->makeAnimalSound();
    delete catClient;
    delete catFactory;

    AnimalFactory* dogFactory = new DogFactory();
    AnimalClient* dogClient = new AnimalClient(dogFactory);
   
dogClient->makeAnimalSound();
    delete dogClient;
    delete dogFactory;

    return 0;
}

Output:

Conclusion

Finally, we can employ the factory design pattern to generate instances of various animal types without requiring knowledge of the specific object implementations. A client class can be developed to utilize the factory for creating instances of the "Animal" class.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience