Creational

Factory Method (Virtual Constructor)

Purpose

Allow subclasses to override a base member function (the Factory method) to decide which class to instantiate based on the dynamic type of the calling class. Factory methods are always virtual.

UML
Behaviour

ConcreteCreator specializes BaseCreator. ConcreteCreator creates only the product it specializes in - ConcreteProduct. There could be many concrete creators each creating its own specialized concrete product.

Example

The Factory pattern is applied to creating different financial products which all share the interface defined by BaseProduct. Each financial product is created by its corresponding creator.

In the code below, the static type of pBC is BaseCreator while its dynamic type is ConcreteCreator. pBC->CreateProduct() calls CreateProduct() in the BaseCreator which internally calls ProductFactory(). The specific ProductFactory() called is determined by the dynamic type of pBC (which is ConcreateCreator). Therefore, ConcreteCreator::ProductFactory() is called which in turn creates the requested product, ConcreteProduct.

Usage

/* Creator Classes */

/* Base Creator: Base class responsible for declaring the Factory method, which always returns an object of type BaseProduct (defined below) */
class BaseCreator
{
// Constructors/Destructors
public:
    BaseCreator() {}
    virtual ~BaseCreator() {}

// Public Interface
public:
    BaseProduct* CreateProduct()
    {
        /* This will call the appropriate virtual method base on the dynamic
        type of the obejct calling CreateProduct() */
        BaseProduct *pProduct = ProductFactory();

        return pProduct;
    }

// Implementation Details
protected:
    /* The Factory method. it is protected because it is not part of the interface but must
    be specialized by derived classes. It must always return a pointer to the base product. 
    This factory method returns a default BaseProduct-derived class */
    virtual BaseProduct* ProductFactory()
    {
        // The BaseCreator returns a default implementation
        return new BaseProduct;
    }
};

/* A BaseCreator derived class that overrides the base Factory method to create an object of type EuroiborProduct. This derived class specializes only in creating objects of type EuroiborProduct */
class EuroiborCreator : public BaseCreator
{
// Constructors/Destructors
public:
    EuroiborCreator() {}
    ~EuroiborCreator() {}

// Public Interface
public:
    /* The overridden Factory method: It must create and return the product it 
    specialzes in. */
   
virtual BaseProduct* ProductFactory()
    {
        // Create the product that this class (EuroiborCreator) specializes in
        return new EuroiborProduct;
    }
};

/* Another BaseCreator-derived class. See descroption for EuroiborCreator class*/
class BundCreator : public BaseCreator
{
// Constructors/Destructors
public:
    BundCreator() {}
    ~BundCreator() {}

    // Public Interface
public:
    /* The overridden Factory method: It must create and return the product it 
    specialzes in. */
   
virtual BaseProduct* ProductFactory()
    {
        // Create the product that this class (BundCreator) specializes in
        return new BundProduct;
    }
};

/* Product Classes */

/* Base class used to define the interface of objects created by the factory method in BaseCreator base class */
class BaseProduct
{
// Constructors/Destructors
public:
    BaseProduct() {}
    virtual ~BaseProduct() {}

// Public Interface
public:
    int GetQuantity() {return -1;}
};

/* Dervied class that implements the interface defined by BaseProduct class */
class EuroiborProduct : public BaseProduct
{
// Constructors/Destructors
public:
    EuroiborProduct() {}
    ~EuroiborProduct() {}

// Public Interface
public:
    int GetQuantity() 
    { 
        // get quantity from somewhere
        return 100;
    }
};

/* Dervied class that implements the interface defined by BaseProduct class */
class BundProduct : public BaseProduct
{
// Constructors/Destructors
public:
    BundProduct() {}
    ~BundProduct() {}

// Public Interface
public:
    int GetQuantity() 
    { 
        // get quantity from somewhere
       
return 1000;
    }
};

int main(int argc, char* argv[])
{
    // Create a Euroibor product
    BaseCreator *pBC1 = new EuroiborCreator;
    EuroiborProduct *pEP = (EuroiborProduct*)pBC1->CreateProduct();
    nRet = pEP->GetQuantity();

    // Create a Bund product
    BaseCreator *pBC2 = new BundCreator;
    BundProduct *pBP = (BundProduct*)pBC2->CreateProduct();
    nRet = pBP->GetQuantity();

    // Clean up
    delete pBC1;
    delete pBC2;
    return 0;
}

Notes