Click here to Skip to main content
Click here to Skip to main content

The Dynamic Registry Factory

, 6 Jan 2010
Rate this:
Please Sign up or sign in to vote.
The idea was to write the system in such a way that every format will have a common interface, and adding (or removing) a new format will not a affect the existing code at all.



This paper will discuss a specic design problem I've come across in the course of a hobby programming project, and the solution I have worked out for it. The solution can be viewed as a specic implementation of what can be considered as a far more general design pattern, which I've decided to call "The dynamic registry factory" (I'm open to suggestions of better names at this point).

The suggested solution will be introduced with thorough explanation of its ins and outs. I will of course admit it is not perfect - it can surely be tweaked and generalized further, but this solution and implementation demonstrate the general idea very well, and account for a good showcase.

The Problem

I had to write a program that will be able to handle many different file formats of various types (MP3, WAV, BMP, etc..) in a very robust, general, and easily extensible manner. The idea was to write the system in such a way that every format will have a common interface, and adding (or removing) a new format will not a affect the existing code at all.

The solution suggested in this paper answers all of the presented requirements, and more. It supports a subset of the original interface: Just enough functionality to allow us to name the correct file format - much like the file command under Linux. It is of course possible to extend this interface at will.

Suggested Design

Known Formats

Figure 1: KnownFormat and FormatMP3 class diagrams.

Every implemented file format in the system has to implement a common KnownFormat interface. This interface supports a single method to retrieve the name of the format.

Every implementing class (FormatMP3 implementation is included as an example) will throw a WrongFormatException exception if the given file does not match the implemented format. The construction succeeds if and only if the given file is in the correct format.

Factories for Known Formats

Figure 2: KnownFormatAbstractFactory and KnownFormatTemplatedFactory class diagrams.

The classic factory design pattern is put to good use here: KnownFormatAbstractFactory defines the common interface for any factory class that is able to generate a KnownFormat object upon receiving a filename. We supply a generic (templated) implementation of a factory for any KnownFormat, with two very useful MACROs that will be introduced in the implementation chapter. The KnownFormatTemplatedFactory is templated on a concrete file format type and provides a functionality of creating a new object of that KnownFormat upon invocations of the create() method. It implements the KnownFormatAbstractFactory interface for an arbitrary KnownFormat implementation.

The Dynamic Registry Factory

Figure 3: KnownFormatFactory class diagram

The KnownFormatFactory is the implementation of the dynamic registry factory. Through invocation of the addFormat() method, which is essentially the gateway to the registration process, it allows easy registration of new supported formats at any given time, with incredible ease of use and without affecting any existing code (using the aforementioned two macros introduced below, in the implementation section). Once the create() method is invoked, the factory goes over all registered formats and attempts to generate a new KnownFormat object through them. An UnknownFormatException will be thrown if the file format could not be matched with any supported file format.


As you have seen, the KnownFormatFactory class allows for any concrete format factory to register on the fly, and the KnownFormatTemplatedFactory allows automatic code generation of a factory for any concrete FileFormat. Combining these two facts, we are able to carry out the registration process by using the two following macros:

// taken from knownformat templatedfactory.h
// include folloing macro within class definition 
#define DECLAREFORMAT(T) const static bool  - 
// inc lude following macro in implementat ion file 
#define IMPLEMENTFORMAT(T) const bool T:: - 
        KnownFormatFactory :: inst ( ) . addFormat (
        KnownFormatAbsFactoryHandle (
        new KnownFormatTemplatedFactory<T>()))

Exploiting the fact that static const members are initialized on the loading of the program, we define a boolean member, which registers with the KnownFormatFactory upon initialization. This nifty trick allows every concrete format to register by using these two very simple macros. To illustrate further, heres how FormatMP3 is implemented:

//  taken from formatmp3.h
class FormatMP3 : public KnownFormat {
     // ...
     private : 
         DECLARE_FORMAT ( FormatMP3 ); 

//  taken from

This is crystal clear, simple, maintainable, and easily reusable. The rest of the implementation can be found included with this paper, and is more or less straightforward.

Future Directions

Thread Safety

The propsed design is not thread safe. In order for the design to function correctly in a multi-threaded environment, some minor changes must be made to the KnownFormatFactory class:

  • A thread safe singleton implementation should be used.
  • Proper locking mechanisms should be used within its member functions.


To conclude, I would like to point out the pros and cons of the suggested technique.


  • Adding support for new formats does not require altering existing code nor recompilation.
  • Adding support for a new format is transparent for all users.
  • It is possible to load formats on the fly, even in a lazy manner (only adding formats when needed). It is possible to load shared (dynamically linked) libraries containing more formats as well.
  • Very scalable design.
  • It is possible (and will not require much effort) to change the registration process such that every format will be registered with its name, to allow lookup of specific formats. For example, this feature can be utilized to implement a save option with many supported formats.


  • This solution forces all supported file formats to implement the same interface, which can be limiting at times (although one could use dynamic cast, it is surely not recommended).

Feel free to observe the enclosed implementation. It contains more details that were omitted from the article itself, but may provide better insight of the proposed design.

Source Code


#ifndef _KNOWN_FORMAT_H_ 
#define _KNOWN_FORMAT_H_

#include <string> 
* This is an abstract class (interface) representing
* a file whose format is known and can be identified.
* It is possible to easily extend this interface in
* the future, to offer broader functionality. 
class KnownFormat {
    public : 
        virtual std::string getFormatName () const = 0; 
        virtual ~KnownFormat () {}; 
#endif // _KNOWN_FORMAT_H


#ifndef _FORMAT_MP3_
#define _FORMAT_MP3_ 

#include "knownformat.h" 
#include "knownformattemplatedfactory.h" 

#include <string>
* This class implements the MP3 file format . 
class FormatMP3 : public KnownFormat {
        FormatMP3 (const std::string &filename );
        virtual std::string getFormatName ( ) const ; 
        const static std::string MAGIC; 
        const static std::string NAME; 
        // declare registration
        DECLARE_FORMAT (FormatMP3); 
#endif // _FORMAT_MP3_

#include "formatmp3.h" 
#include "wrongformatexception.h" 
#include "filenotfoundexception.h" 

#include <vector>
#include <fstream> 

// just implement the registration.

const std::string FormatMP3::MAGIC = "ID3" ; 
const std::string FormatMP3::NAME = "MP3" ; 

FormatMP3::FormatMP3 (const std::string &filename) {
    std::ifstream ifs (filename.c_str());
    if (!ifs) 
        throw FileNotFoundException (filename);
    std::vector<char> read (MAGIC.size(), 0); [0], read.size()); 
    if (std::string(&read[0], read.size()) != MAGIC)
        throw WrongFormatException (filename, NAME); 

std::string FormatMP3::getFormatName () const {
    return NAME; 



#include "types.h" 
#include "knownformat.h" 

#include <string> 

* This is an abstract class (interface) representing
* the common interface to any factory class able to
* create a KnownFormat instance from a given filename.
class KnownFormatAbstractFactory {
        virtual KnownFormatHandle create ( const std::
            string &filename ) const = 0; 

        virtual ~KnownFormatAbstractFactory ( ) {}




#include "types.h"
#include "knownformat.h"
#include "knownformatfactory.h"
#include "knownformatabstractfactory.h"

#include <string />

// include following macro within class definition
// include following macro in implementation file
    KnownFormatFactory::inst().addFormat( \
    KnownFormatAbsFactoryHandle(new KnownFormatTemplatedFactory<t />()))

 * Templated implementation of KnownFormatAbstractFactory
 * The only requiremnt of type T is to have a constructor
 * with the filename as a parameter.
 * The constructor may throw WrongFormatException. 
template <typename T>
class KnownFormatTemplatedFactory : public KnownFormatAbstractFactory {
        virtual KnownFormatHandle create (const std::string &filename) const {
            return KnownFormatHandle(new T(filename));	




#include "types.h"
#include "knownformatabstractfactory.h"

#include <vector>
#include <string>

 * This class is a singleton, holding an isntance of 
 * every format factory in the system.
 * Given a filename it is able to go over all known 
 * formats and generate a KnownFormat object. 
class KnownFormatFactory {
        bool addFormat (KnownFormatAbsFactoryHandle factory);

        KnownFormatHandle create (const std::string &filename) const;

        static KnownFormatFactory &inst ();

        typedef std::vector<KnownFormatAbsFactoryHandle> FactoryVector;
        FactoryVector m_factories;

        KnownFormatFactory () {}
        KnownFormatFactory (const KnownFormatFactory &f) {}
        KnownFormatFactory &operator= (const KnownFormatFactory &f);


#include "knownformatfactory.h"
#include "wrongformatexception.h"
#include "unknownformatexception.h"

bool KnownFormatFactory::addFormat (const KnownFormatAbsFactoryHandle factory) {
    return true;

KnownFormatHandle KnownFormatFactory::create (const std::string &filename) const {
    for (FactoryVector::const_iterator it=m_factories.begin();it != m_factories.end();++it) {
        try {
            return (*it)->create(filename);
        catch (const WrongFormatException &) {
            // next one..
    throw UnknownFormatException(filename);

KnownFormatFactory &KnownFormatFactory::inst () {
    static KnownFormatFactory instance;
    return instance;


#ifndef __TYPES_H__
#define __TYPES_H__

#include <tr1/memory>

// forward decl
class KnownFormat;
class KnownFormatAbstractFactory;

// defining the common handlers (shared pointers)
typedef std::tr1::shared_ptr<KnownFormat>
typedef std::tr1::shared_ptr<KnownFormatAbstractFactory>

#endif // __TYPES_H__



#include <string>
#include <stdexcept>

 * This exception will be thrown when a given filename
 * could not be found.
class FileNotFoundException : public std::runtime_error {
        FileNotFoundException (const std::string &filename) 
            : std::runtime_error("Could not find: " + filename) {}




#include <string>
#include <stdexcept>

 * This exception should be thrown by a KnownFormat 
 * implementation when the given filename isn't of 
 * that specific format.
class WrongFormatException : public std::runtime_error {
        WrongFormatException (const std::string &filename, const std::string &formatname) 
            : std::runtime_error("File " + filename + " does not match format " +
                formatname) {}




#include <string>
#include <stdexcept>

 * This exception will be thrown by the 
 * KnownFormatFactory class when a filename is of an 
 * unknown format.
class UnknownFormatException : public std::runtime_error {
        UnknownFormatException (const std::string &filename) 
            : std::runtime_error("File " + filename + " is of an unknown format") {}


#include "types.h"
#include "knownformat.h"
#include "knownformatfactory.h"

#include <string>
#include <vector>
#include <iostream>
#include <stdexcept>

int main () {
    std::vector<std::string> f;

    std::vector<std::string>::iterator it = f.begin();
    std::vector<std::string>::iterator end = f.end();
    for (;it != end;++it)
        try {
            KnownFormatHandle formatted = 
            std::cout << *it << " is: " <<
                formatted->getFormatName() <<
    catch (const std::exception &e) {
        std::cout << "[info] " << e.what() << std::endl;

    return 0;


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Roman Kecher
Software Developer
Israel Israel
No Biography provided

Comments and Discussions

GeneralMy vote of 2 PinmemberAlexandre GRANVAUD7-Jan-10 21:38 
GeneralArticle's motivation and goals. PinmemberRoman Kecher8-Jan-10 1:38 
Suppose you would like to write an application which is capable of handling many different file formats as input (for example, an mp3 player which is able to play mp3, wav, etc).
Now, what you need is a design, a software architecture, which lets you to EASILY do the following:
1. add new formats
2. modify the existing formats
3. delete formats
4. make use of the supported formats
This paper suggests one such design, and provides an implementation for it. An implementation which is very robust, easy to use, smart, and most of all - allows addition/modifications/removal/usage of all supported formats in a very handy and maintainable manner.
Another important point to take notice of, is this: the suggested architecture is suitable for many other similar problems. For instance, suppose you support many compression algorithms, and you would like to be able to just go over all of them and attempt to compress somethign with each of them, or just use one specific algorithm. But you would not want to name the ones you are using, since it is very possible that new algorithms will be added, and you don't want to constantly update many pieces of code when you add a new algorithm. The suggested design tackles this scenario easily.
I apologize if these goals were not clear from reading the article, and would always love to hear more input.
GeneralMy vote of 1 Pinmemberhaadikhan27-Jan-10 8:49 
GeneralRe: My vote of 1 PinmvpPete O'Hanlon7-Jan-10 9:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140709.1 | Last Updated 6 Jan 2010
Article Copyright 2010 by Roman Kecher
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid