The Abstract Factory pattern in C++

I’m a big fan of data driven design (aka meta-programming.) It is the way to give artists and designers the maximum amount of power short of turning them into programmers (by giving them a scripting language.) One of the biggest obstacles to a fully data driven design in C++ is the complete lack of reflection features in the language. The most important of these is the lack of an ability to instantiate an object at runtime given the name of a class.

The way to get around this is to use the Abstract Factory pattern, but without reflection, there’s no direct way for your abstract factory to create the objects either. You could solve this with a code generator. We are using code generators extensively on Pirates for just this purpose. Unfortunately the biggest of those is part of a proprietary piece of middleware, and comes with tons of extra baggage. The other approach is to use templates and macros to make it easy enough to populate the abstract factory entirely inside the code. This is the approach I’m taking here.

Step by Step

There are three steps involved in getting an abstract factory up and running:

  1. The first step is registering classes with the abstract factory. This is relatively straightforward to do with static data objects and a singleton.
  2. The second step is figuring out how to create the objects. If you are willing to ignore type safety, this is pretty easy. If you are willing to use a different abstract factory for each base class, type safety isn’t so difficult to add.
  3. The third, and most annoying, step is making sure the optimizer doesn’t throw away all your static registration objects, and the classes that go with them. In most cases you won’t be referencing these classes and objects directly, so you have to force the linker to include them by adding references.

Registering classes with the factory

The first part of registering a class with the factory is to build a function that instantiates the class. An example of such a function would look like this:

void *SomeClassFactory()
{
return new SomeClass;
}

The return type is void here, because the abstract factory I’ve built uses a single factory signature. It’s not type safe, but as long as your registrations are all in order it works just fine.
Writing a function like this for every class you want to instantiate by name would be a real drag. Fortunate, templates can help:

template <typename ClassName> void * FactoryFunction()
{
return new ClassName;
}

Now we just need to get a bunch of these factory functions registered by name in the abstract factory. The simplest way to do this is to have a small object that registers itself in its constructor, but allocating memory on the heap at static initialization time is probably not a good idea, so we’ll tweak that approach slightly. Instead of registering itself with the factory directly, the registration objects will build a linked list of themselves, and then the factory will walk that list and perform the registration when it is initialized.

class utFactoryReg {
const char *_name;
utFactoryFn *_function;
utFactoryReg *_next;
static utFactoryReg * s_head;
utFactoryReg(const char *sName,
utFactoryFn *pFactoryFn)
: _name(sName), _function(pFactoryFn)
{
_next = s_head;
s_head = this;
}
};

Now we just need to create one of these objects for each of the classes we want to instantiate by name from the abstract factory. This is as simple as creating a global for the class:

utFactoryReg g_RegisterSomeClass("SomeClass", FactoryFunction);

When the factory itself is initialized it has only to walk the linked list of utFactoryReg objects, and organize them however it needs to for quick lookup.

Creating the objects

Once the factory knows about the classes, instantiating them is relatively straightforward. Just look up the utFactoryReg object and call its factory function:

void *callFactory(const char *sClassName)
{
utFactoryReg *pReg = findRegistration(sClassName);
return pReg;
}

Returning a void * to your callers is a little annoying. Even without type safety we can do better with templates:

template
ClassName create(const char *sClassName)
{
return callFactory(sClassName);
}

If you’re concerned about the type safety of all these casts through void*, you’re right to be. If a caller of create() uses the wrong type the static cast will not catch it and things will go badly. You could mitigate this risk and add more type safety to the factory by making utFactoryReg and FactoryFunction templates. If they return an accurate type you are going to need to templatize your abstract factory class too (whatever callFactory() and findRegistration() live on) and have an instance of that class per base class.

Forcing references

Most of the time it’s a good thing that the linker drops out unreferenced symbols. When you’re trying to initialize a system with static data, though, it just gets in the way. If any of the classes you want to instantiate from the factory are in static libs, you are going to need to jump through some hoops to force them to be referenced. If you don’t want your higher level code to include every possible class, one way to do this is to define the utFactoryReg objects in an array and force a reference to that array. That looks something like this:

// somewhere in your static lib
utFactoryReg g_rGlobalReference [] = {
utFactoryReg("Class1", FactoryFunction),
utFactoryReg("Class2", FactoryFunction),
utFactoryReg("Class3", FactoryFunction)};
int GlobalClassCount() {
return sizeof(g_rGlobalReference)/sizeof(utFactoryReg); }

// somewhere in the code that links to the static lib
GlobalClassCount();

You probably don’t actually care about the class count, so there’s no real reason to catch the result. Just call this at startup sometime before the factory is initialized and it will force the needed reference.

Putting it all together

You can find source for the utFactory and utFactoryReg classes here. The code should be portable, but I’ve only tried it with the included VS2005 projects. This implementation differs slightly from what is described above in that it collects the classes into categories. I’m using the categories as base classes, so I don’t have to worry about accidentally casting an object to an invalid base class. I’ve also added a number of macros to make declaring registrations and reference forcing functions more easily. Use it for whatever you like… this is part of a larger project that I intend to release under an open source license.

If you end up using the code for anything, I would love to hear what you think. I’m also interested to hear other solutions to the problem of instantiation by name in C++, or how the abstract factory approach could be less of a hack. Just leave a comment below or shoot me an email at joe <at-sign> programmerjoe.com.

~Joe


One Response to “The Abstract Factory pattern in C++”

  1. Javier replied on :

    Hi
    Great article.
    I think you may find the Abstract Facory implementation at

    http://sourceforge.net/project/showfiles.php?group_id=229754

    of interest. It contains a great tutorial and I think the implementation ( slightly more advanced than what the author gives in the tutorial) quite good.

    Javier

Leave a Reply