DUECA/DUSIME
Loading...
Searching...
No Matches
Public Member Functions | List of all members
ConglomerateFactory< X, SubConPtr > Class Template Reference

A simple factory, uses subcontractors to create objects. More...

#include <ConglomerateFactory.hxx>

Public Member Functions

 ConglomerateFactory ()
 Constructor.
 
 ~ConglomerateFactory ()
 Destructor.
 
X::ProductBase create (const typename X::Key &key, const typename X::SpecBase &spec) const
 Create one exemplar.
 
bool haveSubcontractor (const typename X::Key &key)
 Check for presence of a specific key.
 
bool addSubcontractor (const typename X::Key &key, const SubConPtr &contractor)
 Add a subcontractor, who can make a specific type of object.
 
bool removeSubcontractor (const typename X::Key &key, const SubConPtr &contractor)
 Remove a subcontractor from the pool.
 
void catalogue (std::ostream &os)
 Print a listing of all on offer.
 

Detailed Description

template<typename X, typename SubConPtr>
class ConglomerateFactory< X, SubConPtr >

A simple factory, uses subcontractors to create objects.

A key defines the class of the desired object, and the subcontractor who will create the object.

What is a "Factory" in software engineering? It has become known as a pattern, a typical solution.

The problem this factory was originally written for may serve as an illustration. I needed a way to flexibly add graphical objects to a scene graph visualization. The objects all behave similar in some respects (they are visible, have a location, can be moved around, stuff like that), but they are all slightly different. Some examples:

And I might want to extend the repertoire later. If you solve that "the classical" way, you have to add a case to your graphics code for each new type of object; e.g. add a model for the Citation with moving gear and control surfaces. That is something I wanted to avoid.

The factory solves it in a different way. This factory has a "map", basically an array indexed with, for example, a string. The elements in the array point to "subsidiaries", pieces of code that are able to create an object of a desired type.

If you want to add a model, now you simply create the code for the model (as before), and then you extend the factory by adding a "subsidiary", a supplier for your factory. There is a template to do that. Now, by simply adding your code to a project, the factory is automatically extended to include the new type of (graphical) object.

There are a number of steps in creating a factory of your own:

Step 1, define a specification of the types in your base product/spec class:

struct MyKey
{
// the key type that differentiates the products/subsidiaries
typedef std::string Key;
// base type of the product (may be pointer, may be reference,
// may be smart pointer)
typedef MyProduct ProductBase;
// base type / only type for specification (what product is made of)
// must be flexible enough to produce all wanted products
typedef MySpecification SpecBase;
};

This definition is typically used by a client of the factory. The exact type of product created is defined by the Key; usually a string-like type. Of course, replace My... etc by the thing you are actually interested in.

Step 2, instantiate a factory with the base type as template parameter. You can use the singleton provided here, and the factory template

MyKey,
MyNewFactory;
Wrapper to create a singleton subsidiary class.
Definition ConglomerateFactory.hxx:239
A simple factory, uses subcontractors to create objects.
Definition ConglomerateFactory.hxx:159
Base subcontractor for the ConglomerateFactory.
Definition ConglomerateFactory.hxx:252

It can be seen that here the subcontractors are stored as a pointer.

Step 3, create a base class for your products. This class defines the interaction with the simulation, in the above example, with the state updating and object drawing code. In this example the base class has virtual functions to access the simulation data and interact with the scene graph code.

Step 4, For each (family of) products, create a class derived from your base class, implementing the desired behaviour.

The derived class should implement the following constructor:

class MySpecificObject: public MyGenericObject
{
MySpecificObject(const MyKey::SpecBase& argument);
...
};
Note that the MyKey::SpecBase (or MySpecification) must be generic
enough to be able create all derived objects. In some cases you might
have to resort to strings with JSON or XML.
Step 5, instantiate a subcontractor to the factory, using the
CFSubcontractor template, e.g.
\code
MySpecificObject_maker
("MySpecificObject",
"Some illustrative information about this object");
Specific subcontractor template.
Definition ConglomerateFactory.hxx:287
X::ProductBase create(const typename X::Key &key, const typename X::SpecBase &spec) const
Create one exemplar.
Definition ConglomerateFactory.hxx:182

Member Function Documentation

◆ create()

template<typename X , typename SubConPtr >
X::ProductBase ConglomerateFactory< X, SubConPtr >::create ( const typename X::Key & key,
const typename X::SpecBase & spec ) const
inline

Create one exemplar.

First finds the subcontractor, based on the key, and then invokes the create function of that subcontractor. Note that this can return a default object when there is no factory for this type!

Parameters
keyType of object that is going to be created.
specSpecifications/arguments for the creation.

◆ addSubcontractor()

template<typename X , typename SubConPtr >
bool ConglomerateFactory< X, SubConPtr >::addSubcontractor ( const typename X::Key & key,
const SubConPtr & contractor )
inline

Add a subcontractor, who can make a specific type of object.

The subcontractor needs to be derived from SubcontractorBase, and implement the create function.

Parameters
keyType of object this subcontractor can create
contractorPointer or reference to the subcontractor
Returns
Double contracting is silently ignored, returns false.

◆ removeSubcontractor()

template<typename X , typename SubConPtr >
bool ConglomerateFactory< X, SubConPtr >::removeSubcontractor ( const typename X::Key & key,
const SubConPtr & contractor )
inline

Remove a subcontractor from the pool.

Parameters
keyType of object this subcontractor can create
contractorPointer or reference to the subcontractor
Returns
false if the subcontractor/type is not found, true otherwise

The documentation for this class was generated from the following file: