User Manual, Developers Guide and API Documentation

StaticFactory

Use StaticFactory

A StaticFactory provides an easy to use interface for plugin handling. Plugins register at a StaticFactory in a decentralised fashion through the use of static, namespace-level objects. That means that at the time your main function gains control, all plugins have already been registered. If you choose to dynamically load shared objects that contain plugins, the plugins get registered during shared object initialisation. There is no central point where you have to register the plugins by hand.

By convention, every StaticFactory template instance is typedefed for your convenience. Assume a collection of plugins that all conform to a given interface, say TestInterface:

struct TestInterface
{
    // this is a base class...
    virtual ~TestInterface() {}
    // some state...
    long foo;
    // some behaviour...
    virtual void set(long) = 0;
};

Then there are two more types declared to work with:

Having these types defined, working with a StaticFactory is pretty simple:

// assert, that the plugin with name "plugin 1" has been registered
ASSERT( TestFactory::knows("plugin 1") );

// to create instances of a plugin, we first need to query
// the factory for a creator.
TestCreator* c = TestFactory::creator("plugin 1");

// once having such a creator, we can create any number of
// plugins using the creator's create method.
TestInterface* p1 = c->create();
// assure that the constructor of the plugin has been called and
// set the attribute foo.
ASSERT( p1->foo == 666 );

// we can call anything the interface provides...
p1->set(23);
ASSERT( p1->foo == 23 );
delete p1;

Write your own plugin

Each StaticFactory template instance is a static class that serves as a factory for objects conforming to a specific interface. The interface includes behaviour, state and signature of the constructor.

Each StaticFactory defines its interface as an abstract class. For example the StaticFactory 'TestFactory' could define a class 'TestInterface'. To write your own plugin, you simply have to write a realisation of the interface and register your plugin at the StaticFactory:

class Plugin1 :
    public TestInterface
{
public:
    Plugin1()
    { foo = 666; }
    virtual void set(long i)
    { foo = i; }
};
STATIC_FACTORY_REGISTER(Plugin1, TestInterface, "plugin 1");

Note:
Don't forget to register your plugin using STATIC_FACTORY_REGISTER.
That's all.

Things get only slightly more difficult, if you want to provide a plugin for a StaticFactory that requests a constructor with another signature. As you saw, plugin instances are created using a creator. For different constructor signatures, you need different creators. Creators are named loosely after their signature by convention. For example LongCreator for interfaces that require the constructor to have one argument of type long, LayerConfigCreator for constructors with the signature (ILayer*, pyconfig::View*).

Assuming a FunkFactory, that requires its plugin implementations to have a constructor with a long as single argument, an implementation could look like:

class Hancock :
    public FunkInterface
{
public:
    Hancock(long _l) : FunkInterface(_l)
    { l = _l; }
    long getIt()
    { return l; }
private:
    long l;
};
STATIC_FACTORY_REGISTER_WITH_CREATOR(Hancock, FunkInterface, "Hancock", LongCreator);

Note:
Use STATIC_FACTORY_REGISTER_WITH_CREATOR when writing plugins with a non-default constructor signature.

Raw meat: create your own StaticFactory

To create your own StaticFactory, you have to provide three things: Defining the interface is simple: just write an abstract class, describing you interface. Assume, you want to implement several classes that conform to a given interface (that have some public state/behaviour):
struct TestInterface
{
    // this is a base class...
    virtual ~TestInterface() {}
    // some state...
    long foo;
    // some behaviour...
    virtual void set(long) = 0;
};

Second you have to choose a creator. If you are lucky, a creator with the desired constructor signature already exists. If not, have a look at LongCreator.hpp or LayerConfigCreator.hpp for examples.

The only thing left to do is to provide some typedefs for convenience:

typedef Creator<TestInterface> TestCreator;
typedef StaticFactory<TestCreator> TestFactory;

If you chose to use a different creator than the default creator Creator, you have to use that instead. Have a look at the complete FunkInterface components for an example of how to create a factory with a different creator:

struct FunkInterface
{
    FunkInterface(long) {}
    virtual ~FunkInterface() {}

    virtual long getIt() = 0;
};
typedef LongCreator<FunkInterface> FunkCreator;
typedef StaticFactory<FunkCreator> FunkFactory;

Generated on Wed Feb 8 03:32:26 2012 for openWNS by  doxygen 1.5.5