DUECA/DUSIME
|
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. | |
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:
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
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:
|
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!
key | Type of object that is going to be created. |
spec | Specifications/arguments for the creation. |
|
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.
key | Type of object this subcontractor can create |
contractor | Pointer or reference to the subcontractor |
|
inline |
Remove a subcontractor from the pool.
key | Type of object this subcontractor can create |
contractor | Pointer or reference to the subcontractor |