Factory Pattern in C++

Factory Pattern in C++

Up until now I never really used the factory pattern that often in C++. Recently I found a use for it in a project I was working on and since I found it useful for my purposes, I thought I might share a tutorial on how the factory pattern can be used in C++.

Now I’m not entirely sure how closely my model fits to the typical factory pattern but as far as I understand factory pattern, it is pretty close if not exact.

Basically a factory consists of an interface class which is common to all of the implementation classes that the factory will create. Then you have the factory class which is usually a singleton class that spawns instances of these implementation classes.

So lets create a quick interface class to start with. In this example I used IAnimal:

class IAnimal
{
public:
virtual int GetNumberOfLegs() const = 0;
virtual void Speak() = 0;
virtual void Free() = 0;
};

Now for simplicity’s sake I used a typedef to define a type for the function that is used by the implementation classes to create instances of IAnimal. This typedef is also used in declaring the map that maps the animal name to the function that creates that particular type of animal. You can use whatever calling convention you like, but for this example I chose __stdcall.

typedef IAnimal* (__stdcall *CreateAnimalFn)(void);

Now comes the factory class. This is a singleton pattern implementation so that only one instance of the factory can ever be instantiated, no more, no less.

// Factory for creating instances of IAnimal
class AnimalFactory
{
private:
AnimalFactory();
AnimalFactory(const AnimalFactory &) { }
AnimalFactory &operator=(const AnimalFactory &) { return *this; }

typedef map FactoryMap;
FactoryMap m_FactoryMap;
public:
~AnimalFactory() { m_FactoryMap.clear(); }

static AnimalFactory *Get()
{
static AnimalFactory instance;
return &instance;
}

void Register(const string &animalName, CreateAnimalFn pfnCreate);
IAnimal *CreateAnimal(const string &animalName);
};

Now comes the implementation classes. These are the classes that implement the IAnimal interface. Here’s a few examples:

// IAnimal implementations
class Cat : public IAnimal
{
public:
int GetNumberOfLegs() const { return 4; }
void Speak() { cout << "Meow" << endl; }
void Free() { delete this; }

static IAnimal * __stdcall Create() { return new Cat(); }
};

class Dog : public IAnimal
{
public:
int GetNumberOfLegs() const { return 4; }
void Speak() { cout << "Woof" << endl; }
void Free() { delete this; }

static IAnimal * __stdcall Create() { return new Dog(); }
};

class Spider : public IAnimal // Yeah it isn't really an animal...
{
public:
int GetNumberOfLegs() const { return 8; }
void Speak() { }
void Free() { delete this; }

static IAnimal * __stdcall Create() { return new Spider(); }
};

class Horse : public IAnimal
{
public:
int GetNumberOfLegs() const { return 4; }
void Speak() { cout << "A horse is a horse, of course, of course." << endl; }
void Free() { delete this; }

static IAnimal * __stdcall Create() { return new Horse(); }
};

Now we need to work out a few definitions of the AnimalFactory class. Specifically the constructor, the Register, and the CreateAnimal functions. The constructor is where you might consider registering your factory functions. Though this doesn’t have to be done here, I’ve done it here for the purposes of this example. You could for instance register your factory types with the factory class from somewhere else in code.

/* Animal factory constructor.
Private, called by the singleton accessor on first call.
Register the types of animals here.
*/
AnimalFactory::AnimalFactory()
{
Register("Horse", &Horse::Create);
Register("Cat", &Cat::Create);
Register("Dog", &Dog::Create);
Register("Spider", &Spider::Create);
}

Now lets implement the Register function. This function is pretty straight forward since I used a std::map to hold the mapping between my string (the animal type) and the create function.

void AnimalFactory::Register(const string &animalName, CreateAnimalFn pfnCreate)
{
m_FactoryMap[animalName] = pfnCreate;
}

And last but not least, the CreateAnimal function. This function accepts a string parameter which co-responds to the string registered in the AnimalFactory’s constructor. When this function receives “Horse” for example, it will return an instance of the Horse class, which implements the IAnimal interface.

IAnimal *AnimalFactory::CreateAnimal(const string &animalName)
{
FactoryMap::iterator it = m_FactoryMap.find(animalName);
if( it != m_FactoryMap.end() )
return it->second();
return NULL;
}

Here’s an example of how to use the above code:

int main( int argc, char **argv )
{
IAnimal *pAnimal = NULL;
string animalName;

while( pAnimal == NULL )
{
cout << "Type the name of an animal or 'q' to quit: ";
cin >> animalName;

if( animalName == "q" )
break;

IAnimal *pAnimal = AnimalFactory::Get()->CreateAnimal(animalName);
if( pAnimal )
{
cout << "Your animal has " << pAnimal->GetNumberOfLegs() << " legs." << endl;
cout << "Your animal says: ";
pAnimal->Speak();
}
else
{
cout << "That animal doesn't exist in the farm! Choose another!" << endl;
}
if( pAnimal )
pAnimal->Free();
pAnimal = NULL;
animalName.clear();
}
return 0;
}
Full Example Source Code (Click to Expand)
#include <string>
#include <map>
#include <iostream>
 
using namespace std;
 
// Base interface
class IAnimal
{
public:
    virtual int GetNumberOfLegs() const = 0;
    virtual void Speak() = 0;
    virtual void Free() = 0;
};
// Create function pointer
typedef IAnimal* (__stdcall *CreateAnimalFn)(void);
 
// Factory for creating instances of IAnimal
class AnimalFactory
{
private:
    AnimalFactory();
    AnimalFactory(const AnimalFactory &) { }
    AnimalFactory &operator=(const AnimalFactory &) { return *this; }
 
    typedef map<string, CreateAnimalFn>   FactoryMap;
    FactoryMap      m_FactoryMap;
public:
    ~AnimalFactory() { m_FactoryMap.clear(); }
 
    static AnimalFactory *Get()
    {
        static AnimalFactory instance;
        return &instance;
    }
 
    void Register(const string &animalName, CreateAnimalFn pfnCreate);
    IAnimal *CreateAnimal(const string &animalName);
};
 
// IAnimal implementations
class Cat : public IAnimal
{
public:
    int GetNumberOfLegs() const { return 4; }
    void Speak() { cout << "Meow" << endl; }
    void Free() { delete this; }
 
    static IAnimal * __stdcall Create() { return new Cat(); }
};
 
class Dog : public IAnimal
{
public:
    int GetNumberOfLegs() const { return 4; }
    void Speak() { cout << "Woof" << endl; }
    void Free() { delete this; }
 
    static IAnimal * __stdcall Create() { return new Dog(); }
};
 
class Spider : public IAnimal // Yeah it isn't really an animal... but you get the idea
{
public:
    int GetNumberOfLegs() const { return 8; }
    void Speak() { }
    void Free() { delete this; }
 
    static IAnimal * __stdcall Create() { return new Spider(); }
};
 
class Horse : public IAnimal
{
public:
    int GetNumberOfLegs() const { return 4; }
    void Speak() { cout << "A horse is a horse, of course, of course." << endl; }
    void Free() { delete this; }
 
    static IAnimal * __stdcall Create() { return new Horse(); }
};
 
/* Animal factory constructor.
Private, called by the singleton accessor on first call.
Register the types of animals here.
*/
AnimalFactory::AnimalFactory()
{
    Register("Horse", &Horse::Create);
    Register("Cat", &Cat::Create);
    Register("Dog", &Dog::Create);
    Register("Spider", &Spider::Create);
}
void AnimalFactory::Register(const string &animalName, CreateAnimalFn pfnCreate)
{
    m_FactoryMap[animalName] = pfnCreate;
}
IAnimal *AnimalFactory::CreateAnimal(const string &animalName)
{
    FactoryMap::iterator it = m_FactoryMap.find(animalName);
    if( it != m_FactoryMap.end() )
        return it->second();
    return NULL;
}
 
int main( int argc, char **argv )
{
    IAnimal *pAnimal = NULL;
    string animalName;
 
    while( pAnimal == NULL )
    {
        cout << "Type the name of an animal or 'q' to quit: ";
        cin >> animalName;
 
        if( animalName == "q" )
            break;
 
        IAnimal *pAnimal = AnimalFactory::Get()->CreateAnimal(animalName);
        if( pAnimal )
        {
            cout << "Your animal has " << pAnimal->GetNumberOfLegs() << " legs." << endl;
            cout << "Your animal says: ";
            pAnimal->Speak();
        }
        else
        {
            cout << "That animal doesn't exist in the farm! Choose another!" << endl;
        }
        if( pAnimal )
            pAnimal->Free();
        pAnimal = NULL;
        animalName.clear();
    }
    return 0;
}


Comments (2)
  • Avatar

    Alex Oct 4 2010 - 11:26 pm

    perfect timing!

    I was just trying to figure out a piece of code that looked quite foreign to me. After I read your article I immediately saw the person was implementing a factory pattern.

  • Avatar

    Cale Oct 5 2010 - 6:02 pm

    Glad you liked it and I’m glad it made sense to you. Yeah there are some areas in the Source SDK that uses the factory pattern as I’m sure you found out.

Leave a reply

You must log in to post a comment.