C++ Abstract Factory Pattern Example

In this article, we will learn how to use and implement the Abstract Factory Pattern in C++ with an example.

Abstract Factory is a creational design pattern that lets you produce families of related objects without specifying their concrete classes.

C++ Abstract Factory Pattern Example

The below diagram shows the generic structure of the Abstract Factory Pattern:
Let's refer the above structure to create an example to demonstrates the usage of the Abstract Factory Pattern in C++:
#include <iostream>

/*
 * Product A
 * products implement the same interface so that the classes can refer
 * to the interface not the concrete product
 */
class ProductA
{
public:
    virtual ~ProductA() {}

    virtual const char* getName() = 0;
    // ...
};

/*
 * ConcreteProductAX and ConcreteProductAY
 * define objects to be created by concrete factory
 */
class ConcreteProductAX : public ProductA
{
public:
    ~ConcreteProductAX() {}

    const char* getName()
    {
        return "A-X";
    }
    // ...
};

class ConcreteProductAY : public ProductA
{
public:
    ~ConcreteProductAY() {}

    const char* getName()
    {
        return "A-Y";
    }
    // ...
};

/*
 * Product B
 * same as Product A, Product B declares interface for concrete products
 * where each can produce an entire set of products
 */
class ProductB
{
public:
    virtual ~ProductB() {}

    virtual const char* getName() = 0;
    // ...
};

/*
 * ConcreteProductBX and ConcreteProductBY
 * same as previous concrete product classes
 */
class ConcreteProductBX : public ProductB
{
public:
    ~ConcreteProductBX() {}

    const char* getName()
    {
        return "B-X";
    }
    // ...
};

class ConcreteProductBY : public ProductB
{
public:
    ~ConcreteProductBY() {}

    const char* getName()
    {
        return "B-Y";
    }
    // ...
};

/*
 * Abstract Factory
 * provides an abstract interface for creating a family of products
 */
class AbstractFactory
{
public:
    virtual ~AbstractFactory() {}

    virtual ProductA *createProductA() = 0;
    virtual ProductB *createProductB() = 0;
};

/*
 * Concrete Factory X and Y
 * each concrete factory create a family of products and client uses
 * one of these factories so it never has to instantiate a product object
 */
class ConcreteFactoryX : public AbstractFactory
{
public:
    ~ConcreteFactoryX() {}

    ProductA *createProductA()
    {
        return new ConcreteProductAX();
    }
    ProductB *createProductB()
    {
        return new ConcreteProductBX();
    }
    // ...
};

class ConcreteFactoryY : public AbstractFactory
{
public:
    ~ConcreteFactoryY() {}

    ProductA *createProductA()
    {
        return new ConcreteProductAY();
    }
    ProductB *createProductB()
    {
        return new ConcreteProductBY();
    }
    // ...
};


int main()
{
    ConcreteFactoryX *factoryX = new ConcreteFactoryX();
    ConcreteFactoryY *factoryY = new ConcreteFactoryY();

    ProductA *p1 = factoryX->createProductA();
    std::cout << "Product: " << p1->getName() << std::endl;

    ProductA *p2 = factoryY->createProductA();
    std::cout << "Product: " << p2->getName() << std::endl;

    delete p1;
    delete p2;

    delete factoryX;
    delete factoryY;

    return 0;
}

Output

Product: A-X
Product: A-Y

Abstract Factory Design Pattern Benefits

  • Abstract Factory design pattern provides an approach to code for interface rather than implementation.
  • Abstract Factory pattern is “factory of factories” and can be easily extended to accommodate more products, 
  • Abstract Factory pattern is robust and avoids the conditional logic of the Factory pattern.

When to use?

  • a system should be independent of how its products are created, composed, and represented
  • a system should be configured with one of multiple families of products
  • a family of related product objects is designed to be used together
  • you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations

Comments