Introduction
I was supposed to write an article about the “Builder” Design Pattern, but a friend suggested writing about the “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 the “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 the Abstract Factory can help us to ease the work, but there are some situations where 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 the Pluggable Factory, you don’t need to change a single line of code to build different packages. So, how does this great thing work?
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>
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;
#define XP_THEME_ID 1
class XPTheme : public ITheme
{
};
class XPThemeMaker : public ThemeMaker
{
public:
XPThemeMaker() : ThemeMaker(XP_THEME_ID){}
private:
ITheme *OnCreateTheme()
{
return new XPTheme();
}
} registerXPTheme;
#define VISTA_THEME_ID 2
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 the registerXPTheme
and registerVistaTheme
variables make the ThemeMaker
constructor to be called at startup. Every concrete Maker class must implement the 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 will just let you play with the 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, and make sure to check my web site for updates.
Good luck!