Thursday, 18 June 2015

Polymorphic factories

Polymorphic factories in Cpp with examples

The static factory( ) method in the previous example forces all the creation operations to be focused in one spot, to that’s the only place you need to change the code. This is certainly a reasonable solution, as it throws a box around the process of creating objects. However, the Design Patterns book emphasizes that the reason for the Factory Method pattern is so that different types of factories can be subclassed from the basic factory (the above design is mentioned as a special case). However, the book does not provide an example, but instead just repeats the example used for the Abstract Factory. Here is ShapeFactory1.cpp modified so the factory methods are in a separate class as virtual functions:


#include "stdafx.h"

#include <iostream>

#include <string>

#include <exception>

#include <vector>

#include <map>

using namespace std;

class MyShapeCls {

public:

virtual void DrawShape() = 0;

virtual void erase() = 0;

virtual ~MyShapeCls() {}

};

class ShapeFactory {

virtual MyShapeCls* create() = 0;

static map<string, ShapeFactory*> VectFatList;

public:

virtual ~ShapeFactory() {}

friend class ShapeFactoryInizializer;

class BadShapeCreation : public exception

{

string strReason;

public:

BadShapeCreation (string strTypeofShape)

{

strReason = "Cannot create strTypeofShape " + strTypeofShape;

}

const char *Show () const

{

return strReason.c_str ();

}

};


static MyShapeCls* createShape(string strId) throw(BadShapeCreation)

{

if (VectFatList.find (strId) != VectFatList.end ())

  return VectFatList[strId]->create ();

else

  throw BadShapeCreation (strId);

}

};

map<string, ShapeFactory*> ShapeFactory::VectFatList;

class CircleShape : public MyShapeCls

{

CircleShape ()

  {} 

public:

void DrawShape () { cout << "CircleShape::DrawShape\n"; }

void erase () { cout << "CircleShape::erase\n"; }

~CircleShape () { cout << "CircleShape::~CircleShape\n"; }

class MyFactory;

friend class MyFactory;

class MyFactory : public ShapeFactory

{

public:

MyShapeCls* create ()

  { return new CircleShape; }

  };

};

class SquareShape : public MyShapeCls

{

  SquareShape ()

    {}

public:

void DrawShape ()

  { cout << "SquareShape::DrawShape\n"; }

void erase ()

  { cout << "SquareShape::erase\n"; }

~SquareShape ()

  { cout << "SquareShape::~SquareShape\n"; }

class MyFactory;

friend class MyFactory;

class MyFactory : public ShapeFactory

{

public:

MyShapeCls* create ()

  { return new SquareShape; }

};

};

class ShapeFactoryInizializer

{

  static ShapeFactoryInizializer ocSingleTone;

ShapeFactoryInizializer ()

{

ShapeFactory::VectFatList["CircleShape"] = new CircleShape::MyFactory;

ShapeFactory::VectFatList["SquareShape"] = new SquareShape::MyFactory;

}

};

ShapeFactoryInizializer ShapeFactoryInizializer::ocSingleTone;

char* shlist[] = { "CircleShape", "SquareShape", "SquareShape", "CircleShape", "CircleShape", "CircleShape", "SquareShape", "" };

int _tmain (int argc, _TCHAR* argv[])

{

vector<MyShapeCls*> vectShapsLst;

try
{

for (char** ppchIndex = shlist; **ppchIndex; ppchIndex++)

vectShapsLst.push_back (ShapeFactory::createShape(*ppchIndex));

}

catch (ShapeFactory::BadShapeCreation e) {

cout << e.Show() << endl;

return 1;

}

for (int i = 0; i < vectShapsLst.size(); i++)

{

vectShapsLst[i]->DrawShape ();

vectShapsLst[i]->erase ();

}

  getchar ();

 return 0;

}



Now the factory method appears in its own class, ShapeFactory, as the virtual create( ). This is a private method which means it cannot be called directly, but it can be overridden. The subclasses of Shape must each create their own subclasses of ShapeFactory and override the create( ) method to create an object of their own type. The actual creation of shapes is performed by calling ShapeFactory::createShape( ), which is a static method that uses the map in ShapeFactory to find the appropriate factory object based on an identifier that you pass it. The factory is immediately used to create the shape object

The output of the above program is
CircleShape::DrawShape

CircleShape::erase

SquareShape::DrawShape

SquareShape::erase

SquareShape::DrawShape

SquareShape::erase

CircleShape::DrawShape

CircleShape::erase

CircleShape::DrawShape

CircleShape::erase

CircleShape::DrawShape

CircleShape::erase

SquareShape::DrawShape

SquareShape::erase



No comments: