Programming with Passion

Make the best out of everything.

Saturday 19 March 2016

Factory in C++

Factory in C++

Factory Pattern || How to implement a factory in C++:

What is the factory pattern?
Ans: 
  • When a method returns one of several possible classes that share a common super class
  • Create a new Enemy in a game
  • Random number generator picks a number assigned to a specific enemy
  • The Factory returns the enemy associated with the number
  • The Class is chosen at run time
When to use a Factory || Factory Pattern?
Ans:
  • When you don't know ahead of time what class object you need
  • When all of the potential classes are in the same subclass hierarchy
  • To Centralize class selection code
  • When you don't want the user to have to know every subclass
  • To Encapsulate Object Creation

Factory Code Example :
#include 
#include 
#include 

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 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;
}

No comments:

Post a Comment