All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
Factories

Overview

The C++ factory pattern is a powerful tool which can be used to create objects using only a tag such as a string. The Qtilities libraries provides an advanced Qt friendly factory pattern implementation which allows the developer to easily create factories, and to manage multiple factories in an plugin extendable application.

This article explains a few different concepts, but everything comes together nicely at the end of the article, thus to get the whole picture you would need to hold out and read the whole page.

Table of contents:

First Steps

Overviews

Creating factories

When creating factories there are a few classes that come into play. Lets look at each of these classes:

The image below provides a visualization of the interaction between these classes.

factory_classes.jpg
Factory Creation Classes

Basic usage of the factory implementation

The factory implementation is best described by an example. In the example we have a base class ExampleBase which is the base class used by the factory. ProduceMe is the class which is registered in the factory and it is able to produce instances of ProduceMe.

// --------------------------------------------
// The following goes into your header file, lets say ProduceMe.h
// --------------------------------------------
#include <QtilitiesCore>
// Be careful of namespace pollution, this is just an example.
using namespace QtilitiesCore;
// Base class:
class ExampleBase {
ExampleBase() {}
virtual ~ExampleBase() {}
}
// ProduceMe class derived from ExampleBase:
class ProduceMe : public ExampleBase {
ProduceMe() : ExampleBase() {}
~ProduceMe() {}
// Make this class a factory item:
static FactoryItem<ExampleBase, ProduceMe> factory;
}
// --------------------------------------------
// The following goes into ProduceMe.cpp
// --------------------------------------------
FactoryItem<ExampleBase, ProduceMe> ProduceMe::factory;
// --------------------------------------------
// You can now produce instances of the ProduceMe class as follows:
// --------------------------------------------
Factory<ExampleBase> exampleFactory;
FactoryItemID produce_me_id("Example Tag");
exampleFactory.registerFactoryInterface(&ProduceMe::factory,produce_me_id);
// We can create instances of ProduceMe as follows:
ExampleBase* base_inst = exampleFactory.createInstance(produce_me_id.tag);
ProduceMe* produceMe_inst = qobject_cast<ProduceMe*> (base_inst);

Identifying items within a factory

In the example above we used the Qtilities::Core::FactoryItemID struct which contains all the information necessary to register and create a specific instance in the factory. This structure has the ability to not only define a tag which can be used to produce the object, it can also provide other information along with the tag. Lets take a look at the information it provides for each factory interface registered:

To produce the object only the tag is required, but to group factory interfaces properly the other fields can be used.

Managing factories

As an application gets bigger there is often a need for multiple factories. When managing factories there's a different set of classes that come into play. Lets look at each of these classes:

While reading through this section it is important to note that the factory management classes can be used with any factory implementation. It is not necessary to use the Qtilities factory classes in order to use the factory management classes.

The IFactoryProvider interface

The goal of the factory provider interface is to expose a set of factories and can be implemented by any object which wish to expose one or more factories to the rest of the application. The image below visualizes this concept.

factory_management.jpg
The Factory Provider Concept

The image above shows the functions which can be used to query factories exposed through the interface.

Managing multiple IFactoryProvider instances

Implementations of the IFactoryProvider interface can be registered in the object manager using the Qtilities::Core::Interfaces::IObjectManager::registerIFactoryProvider() function. Once registered, it is possible to obtain the factory provider interface which contains a specific factory using the Qtilities::Core::Interfaces::IObjectManager::referenceIFactoryProvider() function.

object_manager_ifactoryprovider.jpg
Managing Multiple IFactoryProviders

Bringing it all together: The InstanceFactoryInfo struct

When looking closely at the previous sections, it is observed that we need the following information to create an instance of an object in a factory exposed through the IFactoryProvider interface:

The Qtilities::Core::InstanceFactoryInfo struct was created for this exact reason. It provides all the information needed to locate the needed factory through the object manager, as well as the tag to use in that factory.

The IExportable interface, what does it have to do with factories?

As discussed in the previous section, a Qtilities::Core::InstanceFactoryInfo object contains all the information needed to construct an object somewhere in a factory exposed to the object manager. For this reason any object implementing the Qtilities::Core::Interfaces::IExportable interface must provide an InstanceFactoryInfo object. This way we can reconstruct the object during import operations on the interface. The InstanceFactoryInfo class has constructors for all of the export formats provided by the IExportable interface for this reason.

This gets us to a very important point: When implementing the IExportable interface, the first thing that must be added to the export object (whether it is a QDataStream during binary exporting, or a QDomElement during XML exporting) is the information contained by InstanceFactoryInfo. During import we get this information, construct the object and the call the import functions on the reconstructed object.

Ready to use factory and factory classes

The object manager provides a ready to use factory, called the Qtilities factory in the documentation and by Qtilities::Core::Constants::qti_def_FACTORY_QTILITIES name in the Qtilities sources. This factory can produce any QObject based class for which a factory interface was registered in the object manager. Many of the Qtilities classes are registered by default and can be produced using this factory (See Visual overview of factories using the Debug plugin).

Lets look at an example where we create change the ProduceMe class in the above example. We make it QObject based, register it in the Qtilities factory and then produce it:

// --------------------------------------------
// The following goes into your header file, lets say ProduceMe.h
// --------------------------------------------
// ProduceMe class derived from QObject:
class ProduceMe : public QObject {
ProduceMe(Qbject* parent = 0) : QObject(parent) {}
~ProduceMe() {}
// Make this class a factory item:
static FactoryItem<QObject, ProduceMe> factory;
}
// --------------------------------------------
// The following goes into ProduceMe.cpp
// --------------------------------------------
FactoryItem<QObject, ProduceMe> ProduceMe::factory;
// --------------------------------------------
// In the application code:
// --------------------------------------------
// Register ProduceMe in the Qtilities factory:
FactoryItemID produce_me_id("Example Tag");
OBJECT_MANAGER->registerFactoryInterface(&ProduceMe::factory,produce_me_id);
// Now we can produce it as follows:
InstanceFactoryInfo instance_factory_info(qti_def_FACTORY_QTILITIES,produce_me_id.tag,"ObjectNameWhenCreated");
IFactoryProvider* ifactory = OBJECT_MANAGER->referenceIFactoryProvider(instance_factory_info.d_factory_tag);
if (ifactory) {
QObject* obj = ifactory->createInstance(instance_factory_info);
obj->setObjectName(instance_factory_info.d_instance_name);
ProduceMe* produceMe_inst = qobject_cast<ProduceMe*> (obj);
}

Visual overview of factories using the Debug plugin

The Qtilities::Plugins::Debug plugin provides a visual overview of the factory provider interfaces registered in the object manager as well as the tags in each interface. This is shown in the image below:

debugging_state_factories.jpg
Factories Overview In The Debug Plugin


Qtilities : Reference Documentation Back to top Copyright © 2009-2013, Jaco Naudé