| How to code like professionals? Part 3: Pluggable Factory |
Introduction
I was supposed to write an article about "Builder" Design Pattern, but a friend suggests me to write about "Pluggable Factory". After all, I thought that it would be a better idea too! So here you can read about one of the greatest Design Patterns called "Pluggable Factory".
Pluggable Factory
Let's continue with the example in the previous article. We wanted to create an application which supports multiple themes. You saw how Abstract Factory can help us to ease the work, but there are some situations which we want to register new factories at runtime. For example consider you want to build different release packages each of which containing a set of themes. By using Pluggable Factory, you don't need to change a single line of code to build different packages. So how this great thing works?
Pluggable Factory needs a new type of classes called Makers. The main functionality is behind the base Maker class which handles registering the set of concrete Maker classes. In this example we have three maker classes ThemeMaker(base), XPThemeMaker and VistaThemeMaker.
#include <stdio.h>
#include <vector>
#include <map>
/*
* Abstract Theme
*/
class ITheme
{
//...
};
class ThemeMaker
{
public:
typedef std::map <int, ThemeMaker*> RegisteryRecord;
ThemeMaker(int themeID)
{
registry.insert(std::make_pair(themeID, this));
}
static ITheme *CreateTheme(int themeID)
{
RegisteryRecord::iterator record = registry.find(themeID);
if(record!=registry.end())
{
return (*record).second->OnCreateTheme();
}
printf("The requested theme is not available.\n");
return 0;
}
static int GetRegisteredThemesNumber()
{
return (int)registry.size();
}
protected:
virtual ITheme *OnCreateTheme() = 0;
private:
static RegisteryRecord registry;
};
ThemeMaker::RegisteryRecord ThemeMaker::registry;
/*
* XP Theme
*/
#define XP_THEME_ID 1 /* unique theme id */
class XPTheme : public ITheme
{
//...
};
class XPThemeMaker : public ThemeMaker
{
public:
XPThemeMaker() : ThemeMaker(XP_THEME_ID){}
private:
ITheme *OnCreateTheme()
{
return new XPTheme();
}
} registerXPTheme;
/*
* VistaTheme
*/
#define VISTA_THEME_ID 2 /* unique theme id */
class VistaTheme : public ITheme
{
//...
};
class VistaThemeMaker : public ThemeMaker
{
public:
VistaThemeMaker() : ThemeMaker(VISTA_THEME_ID){}
private:
ITheme *OnCreateTheme()
{
return new VistaTheme();
}
} registerVistaTheme;
|
The base Maker class uses a static registry to store concrete Maker classes. Note that declaring registerXPTheme and registerVistaTheme variables make the ThemeMaker constructor to be called at startup. Every concrete Maker class must implement OnCreateTheme virtual function which handles creating the actual theme class. You can easily use the base Maker class to make new themes in this way:
void main()
{
ITheme *theme = 0;
theme = ThemeMaker::CreateTheme(1);
printf("Number of available themes: %d\n", ThemeMaker::GetRegisteredThemesNumber());
}
|
It's also a good idea to implement a set of enumeration functions for the ThemeMaker class, but I just let you play with a code because I want to go sleep! OK, at last if you have comments or questions let me know by writing to vkazemi {at} gmail.com.
Good Luck |
Posted on : 06 Sep 2006 Vahid Kazemi |