PhotoSell

Tuesday, August 23, 2011

Factory methods



Factory methods
Factory functions or factory method pattern is an object oriented design pattern to implement the concept of factories. The idea behind factory method is to enable creation of objects without knowing the exact class that will be created. This simplifies the idea of abstraction, prevents duplicate code, prevent unnecessary include and allowing the composing class not to concern regarding the created class.
Let’s take for example a conversion program. Our program receives a number as input, the type of conversion need to be done and will output the result of the conversion. One way doing this is writing a conversion method with a long switch-case which will probably look like this:
float Convert(float _input, int _type)
{
Float res = 0;
Switch (_type)
{
Case 1:

Break;
Case 2:

Break;


}
Return res;
}
This will work fine, but every new conversion type must be added to this conversion function. Now let’s make things a bit more complicated, let’s assume that we need to perform input and output validation, which is different for every converter. It’s bit more complicated but still easy using object-oriented classes. The new code should look something like this:
BaseCoverter *CreateConverter(int _type)
{
Switch (_type)
{
Case 1: return new …
Case 2: return new …


}
Return new BaseConverter();
}
float Convert(float _input, int _type)
{
BaseCoverter *pConverter = CreateConverter(_type);
If (pConverter->isValidInput(_input) != true)
Return 0;
Float res = pConverter->convert(_input);
If (pConverter->isValidOutput(res) != true)
Return 0;
delete pConverter;
Return res;
}
Now we still have the same long switch-case function, just this time it moved to the converter creation function. This is where factory method comes in handy, if we could have just get rid of this long switch-case function can create the converters dynamically then it would have been much easier.
Here is an example of a simple factory class (.h):
#include
using namespace std;

class FactoryBase{};

// Factory method for creating the class
typedef FactoryBase* FactoryMethod();

// Internal - the data structure used to save the conversion map.
typedef map TypeToClassMap;

// Internal - will be used to get the pointer to the global factory class.
class Factory;
Factory* GetFactory();

class Factory
{
public:
Factory();
virtual ~Factory();

static FactoryBase *CreateClass(IN int _type);
static void RegisterClass(IN int _type, IN FactoryMethod *_creator);
static void UnregisterClass(IN int _type);

protected:
static TypeToClassMap* m_pTypeToClassMap;
};

// Add this MACRO in the public part of the class declaration.
// This will be used to register the class in the global factory and a constuctor
// will be called when Factory::CreateClass() is triggered.
#define DECLARE_CREATEABLE_CLASS(class_id, class_type)\
static FactoryBase *FactoryMethod()\
{ return (new class_type()); }\
static void RegisterClass()\
{ GetFactory()->RegisterClass(class_id, FactoryMethod); }\
static void UnregisterClass()\
{ GetFactory()->UnregisterClass(class_id); }

// This MACRO should be called only once for class in its .cpp file and only
// if DECLARE_CREATEABLE_CLASS was used in the *.h file.
// It is used in order to register the class in the global factory.
#define IMPLEMENT_CREATEABLE_CLASS(class_type)\
class reg_class_##class_type\
{\
public:\
reg_class_##class_type() { class_type::RegisterClass(); }\
~reg_class_##class_type() { class_type::UnregisterClass(); }\
};\
reg_class_##class_type class_##class_type

The static variable initialization in cpp file:
#include "stdafx.h"
#include "Factory.h"

TypeToClassMap* Factory::m_pTypeToClassMap = NULL;
Factory g_pFactory;

Factory* GetFactory()
{
return &g_pFactory;
}

Factory::Factory()
{
if (m_pTypeToClassMap == NULL)
m_pTypeToClassMap = new TypeToClassMap();
}

Factory::~Factory()
{
delete m_pTypeToClassMap;
m_pTypeToClassMap = NULL;
}

FactoryBase* Factory::CreateClass(IN int _type)
{
if (m_pTypeToClassMap == NULL)
return NULL;

TypeToClassMap::iterator iter = m_pTypeToClassMap->find(_type);
if (iter != m_pTypeToClassMap->end())
return iter->second();

return NULL;
}

void Factory::RegisterClass(IN int _type, IN FactoryMethod *_creator)
{
if (m_pTypeToClassMap == NULL)
m_pTypeToClassMap = new TypeToClassMap();

(*m_pTypeToClassMap)[_type] = _creator;
}

void Factory::UnregisterClass(IN int _type)
{
if (m_pTypeToClassMap != NULL)
m_pTypeToClassMap->erase(_type);
}

Now I’ll explain the implementation of the class. In the first part we declare our factory class; this class will hold the mapping between the type values to the converter class. The class contains 3 static functions:
1. RegisterClass – this is used to register a new converter in the system.
2. UnregisterClass – this is used when we are done with the converter and want to delete it so it will not be usable again until new registration.
3. CreateClass – this is used whenever we want to dynamically create a converter. The return value of this function is a new instance of converter class or NULL if the type is not registered.
The second part contain two macros used to declare a class as a converter class and to register it in the factory class.
• DECLARE_CONVERTER – should be placed within the class declaration file (.h).
• REGISTER_CONVERTER – should be placed within the class implementation file (.cpp)

Here is the declaration of the base converter class (BaseConverter.h):
#include "Factory.h"

class BaseConverter : public FactoryBase
{
public:
BaseConverter() {}
virtual ~BaseConverter() {}

virtual bool isValidInput(float _input) { return false; }
virtual bool isValidOutput(float _input) { return false; }
virtual float convert(float _input) { return 0; }

DECLARE_CREATEABLE_CLASS(1, BaseConverter);
};
And the implementation (BaseConverter.cpp):
#include "StdAfx.h"
#include "BaseConverter.h"

IMPLEMENT_CREATEABLE_CLASS(BaseConverter);

Notice how I use DECLARE_CREATABLE_CLASS & IMPLEMENT_CREATABLE_CLASS to declare and register my class in the global factory. So now, we can simplify and generalize the conversion function and just use the factory class to create the converter. The new function should look like this:
float Convert(float _input, int _type)
{
BaseConverter *pConverter = ((BaseConverter *)(Factory::CreateClass(_type)));
if (pConverter == NULL)
return 0;

if (pConverter->isValidInput(_input) != true)
{
delete pConverter;
return 0;
}
float res = pConverter->convert(_input);
if (pConverter->isValidOutput(res) != true)
{
delete pConverter;
return 0;
}
delete pConverter;
return res;
}
This implementation is plain, simple, abstract, generic and doesn’t require long switch-case creation functions. If I want to add new convertors, all I need to do is just to write a new converter class, register it and perform some minor adjustments to the GUI so the user can pick it up in his selection.

So this is all for now (about factory method) and I hope this post was clear enough.

AdSense

הודעה זו מאשרת את בעלותי על האתר וכי האתר כפוף לתקנון של תוכנית Google AdSense ולתנאים וההגבלות שלה. ca-pub-7405817156767865

Tuesday, June 14, 2011

Tiger Leaping Gorge - The waterfall



One amazing picture, was taken almost under the waterfall, just few steps away.



Tiger Leaping Gorge - Along the road

These amazing photos were taken along the Tiger Leaping Gorge track road in China.





Black Dragon Pool Park

The most famous picture of the black dragon pool, just without the photoshop snowy mountain in the background.

Sunset in Fe La Si

Sunset to snowy mountains in Fe La Si, China

Blue Mountain Valley - Green Lagoon

This picture was taken near a beautiful green lagoon in blue mountain valley in China.