My question is more or less identical to the one at Need a design pattern to remove enums and switch statement in object creation However I don't see that the abstract factory pattern suits well here.
I'm currently planning the refactoring/reimplementation of some existing DAL/ORM mixture library. Somewhere in the existing code there is code that looks like this:
class Base
{
static Base * create(struct Databasevalues dbValues)
{
switch(dbValues.ObjectType)
{
case typeA:
return new DerivedA(dbValues);
break;
case typeB:
return new DerivedB(dbValues);
break;
}
}
}
class DerivedA : public Base
{
// ...
}
class DerivedB : public Base
{
// ...
}
So the library responsible for database communication populates a struct with all information about the database entity and then the above create() method is called to actually create the corresponding object in the ORM.
But I don't like the idea of a base class knowing of all its derived classes and I don't like the switch statement either. I also would like to avoid creating another class just for the purpose of creating those Objects. What do you think about the current approach? How would you implement this functionality?
This has been discussed here milliions of times. If you don't want to create a separate factory class, you can do this.
class Base
{
public:
template <class T>
static void Register (TObjectType type)
{
_creators[type] = &creator<T>;
}
static Base* Create (TObjectType type)
{
std::map <TObjectType, Creator>::iterator C = _creators.find (type);
if (C != _creators.end())
return C->second ();
return 0;
}
private:
template <class T>
static Base* creator ()
{
return new T;
}
private:
typedef Base* (::*Creator) ();
static std::map <TObjectType, Creator> _creators;
};
int main ()
{
Base::Register <Derived1> (typeA);
Base::Register <Derived2> (typeB);
Base* a = Base::Create (typeA);
Base* b = Base::Create (typeB);
}
Let's say you replace the switch with a mapping, like map<ObjectType, function<Base* (DatabaseValues&)>>.
Now, the factory (which may or may not live in the base class), doesn't need to know about all the subclasses.
However, the map has to be populated somehow. This means either something populates it (so your knowing about all subclasses problem has just been pushed from one place to another), or you need subclasses to use static initialization to register their factory functions in the map.
No matter what you do, you'll need either switch-case or some other construct that will just hide similar logic.
What you can and should do, however, is remove the create method from your Base - you're totally correct it shouldn't be aware of it's derived ones. This logic belongs to another entity, such as factory or controller.
Just don't use enums. They are not OO construction, that was why JAVA did not have them at the beginning (unfortunately the pressure was too big to add them).
Consider instead of such enum:
enum Types {
typeA,
typeB
};
this construction, which do not need switch (another non OO construction in my opinion) and maps:
Types.h
class Base;
class BaseFactory {
public:
virtual Base* create() = 0;
};
class Types {
public:
// possible values
static Types typeA;
static Types typeB;
// just for comparison - if you do not need - do not write...
friend bool operator == (const Types & l, const Types & r)
{ return l.unique_id == r.unique_id; }
// and make any other properties in this enum equivalent - don't add them somewhere else
Base* create() { return baseFactory->create(); }
private:
Types(BaseFactory* baseFactory, unsigned unique_id);
BaseFactory* baseFactory;
unsigned unique_id; // don't ever write public getter for this member variable!!!
};
Types.cpp
#include "Types.h"
#include "Base.h"
#include "TypeA.h"
#include "TypeB.h"
namespace {
TypeAFactory typeAFactory;
TypeBFactory typeAFactory;
unsigned unique_id = 0;
}
Types Types::typeA(&typeAFactory, unique_id++);
Types Types::typeA(&typeBFactory, unique_id++);
So your example (if you really would need this function then):
class Base
{
static Base * create(struct Databasevalues dbValues)
{
return dbValues.ObjectType.create();
}
};
Missing parts should be easy to implement.
Related
You may have heard of the Entity Component System, where everything is an Entity and each entity has a list of Components which control its functionality.
I am trying to find out how to store different objects (each inherit Component) in an array and be able to get an object out of that array based on their type.
The first solution I can think of would be to have an enum for the types of objects inheriting component:
enum ComponentType : unsigned char // There will never be more than 256 components
{
EXAMPLE_COMPONENT,
ANOTHER_EXAMPLE_COMPONENT,
AND_ANOTHER_EXAMPLE_COMPONENT
};
Then Component base class has a ComponentType type; with a getter, and each child component sets its type e.g:
ExampleComponent::ExampleComponent()
{
type = EXAMPLE_COMPONENT;
}
And then I'd have a GetComponent function:
Component* Entity::GetComponent(ComponentType type)
{
for (unsigned int i = 0; i < m_components.size(); i++)
{
if (m_components.at(i).GetType() == type)
{
return &m_components.at(i);
}
}
return nullptr;
}
// Note: m_components is an std::vector;
And then finally you would call GetComponent e.g:
(ExampleComponent*) component = entity.GetComponent(EXAMPLE_COMPONENT);
The problem with this is that you need an enum for each type of component and you also have to cast the component after using GetComponent to make sure you can access its own member variables.
Does anyone know of a proper way of doing this where there is no need for an enum and there is no need to cast the component? If there is a solution that still requires a type variable to be stored in each component it preferably would be a byte and can't be any bigger than 4 bytes.
Edit: I also don't want to use templates
Thanks in advance!
David
Your approach simulates polymorphism: Having the type as a member and an if statement checking for that type is typically a indication to make use of a class hierarchy. You already stated that you want to use objects derived from the Componenttype, so you should also make proper use of polymorphism.
The second problem in your approach is that you want to filter for a "specific type", which more or less is equivalent to a downcast — i.e. a dynamic_cast<>(): When you pass a certain ComponentType to Entity::GetComponent(), it returns a pointer to Component, but the object behind that pointer is always an object of a specific derived class: In your example you always get an ExampleComponent object, when you pass EXAMPLE_COMPONENT to that function.
The following question arises then naturally: What do you want to do with the object returned by this function? You can only call methods from the Component interface/class, but no method from the derived class! So the downcast hardly makes sense at all (it would, if you would return a pointer to an object of a class derived from Component.
Here is how it looks like using polymorphism and with the downcast in the getComponent() method, returning a pointer to a derived class — note that the method is a template to conveniently implement this for every class derived from Component:
#include <string>
#include <vector>
#include <iostream>
class Component {
public:
virtual std::string getType() = 0;
};
using ComponentContainer = std::vector<Component*>;
class AComponent : public Component { public: virtual std::string getType() { return "A"; }; };
class BComponent : public Component { public: virtual std::string getType() { return "B"; }; };
class CComponent : public Component { public: virtual std::string getType() { return "C"; }; };
class Entity {
public:
template <typename T>
T* getComponent();
void putComponent(Component* c) { m_components.push_back(c); }
private:
ComponentContainer m_components;
};
template<typename T>
T* Entity::getComponent()
{
T* t = nullptr;
for (auto i : m_components) {
if ((t = dynamic_cast<T*>(i)) != nullptr)
break;
}
return t;
}
int main()
{
Entity e;
e.putComponent(new AComponent{});
e.putComponent(new BComponent{});
Component* c;
if ((c = e.getComponent<AComponent>()) != nullptr)
std::cout << c->getType() << std::endl;
// delete all the stuff
return 0;
}
The heavy use of dynamic_cast<>() is problematic both from performance and from design point of view: It should only be used rarely, if ever.
So the design problem may be that everything is stored in a single container? You could instead use several containers, based on "behaviour". As behaviour is implemented in an ECS as a derived class or interface, a getComponent()-similar method of this entity would only return objects of certain (sub-)interfaces. These components would then all implement a given interface method, so the need for down-casting would be eliminated.
For example, given you have "drawable components", this suggests the hierarchy:
// Drawable interface
class DrawableComponent : public Component {
public:
virtual void draw() const = 0;
};
// Drawable objects derive from DrawableComponent
class DComponent : public DrawableComponent {
public:
virtual void draw() const { /* draw the D component */ }
};
Then, an entity could have a container of DrawableComponent objects and you would just iterate over those objects and call draw() on each:
using DrawableContainer = std::vector<DrawableComponent*>;
// m_drawables is a memober of Entity with above type
const DrawableContainer& Entity::getDrawables() { return m_drawables; }
// then just draw those objects
for (auto d : entity.getDrawables())
d->draw(); // no downcast!
I have multiple classes that share a common base class, like this:
class Base {};
class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};
Now, I need to know which of these derived classes to instantiate during runtime (based on input). For example, if input is "DerivedA", I need to create a DerivedA object. The input is not necessarily a string, it could be an integer as well - the point is that there is a key of some sort and I need a value to match the key.
The problem is, though, how do I instantiate the class? C++ does not have built-in reflection like C# or Java. A commonly suggested solution I've found is to use a factory method like this:
Base* create(const std::string& name) {
if(name == "DerivedA") return new DerivedA();
if(name == "DerivedB") return new DerivedB();
if(name == "DerivedC") return new DerivedC();
}
This would be sufficient if there's only a couple of classes, but becomes cumbersome and probably slow if there's tens or hundreds of derived classes. I could quite easily automate the map creation process to produce a std::map<std::string, ***>, but I have no idea what to store as the value. AFAIK, pointers to constructors are not allowed. Again, if I do a factory using this map, I'd still need to write a factory method for each type, making it even more cumbersome than the example above.
What would be an efficient way to handle this problem, especially when there's lots of derived classes?
You can always store std::function<Base*()> as you always return pointers to Base from your create function:
class Base {};
class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};
Base* create(const std::string& type)
{
static std::map<std::string, std::function<Base*()>> type_creator_map =
{
{"DerivedA", [](){return new DerivedA();}},
{"DerivedB", [](){return new DerivedB();}},
{"DerivedC", [](){return new DerivedC();}}
};
auto it = type_creator_map.find(type);
if(it != type_creator_map.end())
{
return it->second();
}
return nullptr;
}
As Angew suggested, you should return std::unique_ptr instead of raw pointers. If the user of create function wants a raw pointer or a std::shared_ptr he/she can just "grab" the raw pointer and use it.
UPDATE:
Next method provides a convenient semi-automatic way of registering new types without changing old code.
I don't recommend using it because it depends on the linker (the moment of creating global variables might be delayed), they way you compile the code(executable, static library, dynamic library), it allocates memory before main() starts and it creates weird named global variables.
Use it only if you really know what you are doing and know on what platforms you are using the code!
class Base {};
std::map<std::string, std::function<Base*()>>& get_type_creator_map()
{
static std::map<std::string, std::function<Base*()>> type_creator_map;
return type_creator_map;
}
template<typename T>
struct RegisterTypeHelper
{
RegisterTypeHelper(const std::string& id)
{
get_type_creator_map()[id] = [](){return new T();};
}
};
Base* create(const std::string& type)
{
auto& type_creator_map = get_type_creator_map();
auto it = type_creator_map.find(type);
if(it != type_creator_map.end())
{
return it->second();
}
return nullptr;
}
#define RegisterType(Type) static RegisterTypeHelper<Type> register_type_global_##Type(#Type)
class DerivedA : public Base {};
RegisterType(DerivedA);
class DerivedB : public Base {};
RegisterType(DerivedB);
class DerivedC : public Base {};
RegisterType(DerivedC);
One way to solve this is to use the design pattern Prototype.
Basically, you wouldn't create the derived class objects by direct initialisation, but by cloning a prototype instead. Your create() function is actually a realisation of the Factory method design pattern. You can use Prototype inside the implementation, like this:
class Base
{
public:
virtual ~Base() {}
virtual Base* clone() = 0;
};
class DerivedA : public Base
{
public:
virtual DerivedA* clone() override { return new DerivedA; }
};
Base* create(const std::string &name)
{
static std::map<std::string, Base*> prototypes {
{ "DerivedA", new DerivedA },
{ "DerivedB", new DerivedB },
{ "DerivedC", new DerivedC }
};
return prototypes[name]->clone();
}
Error checking left out of the example for brevity.
In a real project, you should of course use a smart pointer (such as std::unique_ptr) instead of raw pointers to manage the objects' lifetimes.
I could quite easily automate the map creation process to produce a std::map, but I have no idea what to store as the value.
You need to store a factory method as the value, e.g. a static method which creates an instance of your class:
class Base {};
class DerivedA : public Base {
public:
static Base* create();
...
}
...
Base* DerivedA::create() {
return new DerivedA();
}
You can then implement the name/lookup through a map like
typedef Base* (*FACTORY_FUNCTION)();
std::map<std::string, FACTORY_FUNCTION> factories;
...
factories["ClassA"] = ClassA::create;
if I do a factory using this map, I'd still need to write a factory method for each type
Since these factory methods are very simple, you can automate their creation by a simple code generation tool (e.g. with a simple shell script). You can either maintain a list of classes, or retrieve this list from your header files (e.g. by grepping for the class keyword and retrieve the succeeding class name, or even better by using some analysis tool which properly parses the header files).
With that information, you can automatically create the necessary code to automatically add the factory methods to each class. With the same approach, you could also generate the registration function which needs to be called once, so that your objects are getting registered.
I have certain functionality encapsulated in classes which I use in another class. I think this is called composition.
class DoesSomething01
{
public:
DoesSomething01();
void functionality01();
void functionality02();
};
class DoesSomething02
{
public:
DoesSomething02();
void functionality01();
void functionality02();
};
class ClassA
{
public:
ClassA();
private:
DoesSomething01 *m_doesSomething01;
DoesSomething02 *m_doesSomething02;
};
If I have now a ClassB which "knows" ClassA and have to use/execute functionality01 and/or functionality02 of classes DoesSomething01 and/or DoesSomething02 I see two possibilities:
a) Add methods like this to ClassA to provide ClassB direct access to DoesSomething01 and/or DoesSomething02:
DoesSomething01 *getDoesSomething01() { return *m_doesSomething01; }
DoesSomething02 *getDoesSomething02() { return *m_doesSomething02; }
ClassB could then do something like this:
m_classA->getDoesSomething01()->functionality01();
b) Add (in this case four) methods to ClassA which forwards the method calls to DoesSomething01 and DoesSomething02 like this:
void doesSomething01Functionality01() { m_doesSomething01->functionality01(); }
void doesSomething01Functionality02() { m_doesSomething01->functionality02(); }
void doesSomething02Functionality01() { m_doesSomething02->functionality01(); }
void doesSomething02Functionality02() { m_doesSomething02->functionality02(); }
Which option is better and why?
What are the advantages/disadvantages of each option?
First option can be considered a code smell. According to Robert C. Martin's 'Clean Code' it is "Transitive Navigation" and should be avoided. Quoting the author:
In general we don’t want a single module to know much about its
collaborators. More specifically, if A collaborates with B, and B
collaborates with C, we don’t want modules that use A to know about C.
(For example, we don’t want a.getB().getC().doSomething();.)
Second option looks better. It is classical use of Facade pattern. And it is better, because it hides other functionalities of classes DoesSomthing01 and DoesSomthing02. Then you ve'got simplified view of it which is easier to use than 1st option.
Edit: there is also one more thing. You've got two classes which have the same functionalites and are aggregated by other class. You should consider using Stratey pattern here. The your code will look like this:
class DoesSomething
{
public:
virtual void functionality01() = 0;
virtual void functionality02() = 0;
}
class DoesSomething01 : DoesSomething
{
public:
DoesSomething01();
void functionality01();
void functionality02();
};
class DoesSomething02 : DoesSomething
{
public:
DoesSomething02();
void functionality01();
void functionality02();
};
class ClassA
{
public:
ClassA();
DoesSomething* doesSomething(); // Getter
void doesSomething(DoesSomething* newDoesSomething); // Setter
// ...
private:
DoesSomething *m_doesSomething;
};
Then you will need only two method instead of four:
void doesFunctionality01() { m_doesSomething->functionality01(); }
void doesFunctionality02() { m_doesSomething->functionality02(); }
The first scenario is a violation of law of Demeter, which says that a class can only talk to its immediate friends. Basically the problem with the first approach is that any change in the inner classes DoSomething01 and DoSomething02 will trigger a change in Class A as well as Class B because both classes are now directly dependent on these inner classes.
The second option is better as it encapsulates the class B from inner classes but a side effect of this solution is that now class A has a lot of methods that does nothing fancy except for delegating to its inner classes. This is fine but imagine if DoSomething01 has an inner class DoSomething03 and class B needs to access its functionality without directly knowing about it than the class A would need to have another method that would delegate to DoSomething01 that would in turn delegate to DoSomething03. In this case I think it is better to let class B directly know about DoSomething01 otherwise class A is going to have a huge interface that simply delegates to its inner classes.
If there are many classes and/or many methods to be called it makes sense to invent
an interface in the form of an abstract parent class:
class SomeInterface
{
public:
SomeInterface(){}
virtual void functionally01() = 0;
virtual void functionally02() = 0;
}
DoesSomthing01 and other classes would then inherit this class:
class DoesSomthing01 : public SomeInterface
and implement the methods.
If it make sense to associate a key with the instantiation of such a class
you could store these objects in ClassA e.g. using a map (here I
use an integer as the key):
class ClassA
{
private:
std::map<int, SomeInterface*> m_Interfaces;
public:
SomeInterface* getInterface(const int key)
{
std::map<int, SomeInterface*>::iterator it(m_Interfaces.find(key));
if (it != m_Interfaces.end())
return it->second;
else
return NULL;
}
};
From ClassB you could then access them
int somekey = ...;
SomeInterface *myInter = m_classA->getInterface(somekey);
if (myInter)
myInter->functionally01();
This way you have just one access method (getInterface()) independent
of the number of objects.
In order to encode the access to the methods using a key you could
create a map which maps a key onto a closure or a simple switch statement:
in SomeInterface:
public:
void executeMethod(const int key)
{
switch(key)
{
case 1: functionally01(); break;
case 2: functionally01(); break;
default:
// error
}
int methodKey = ...;
int objectKey = ...;
SomeInterface *myInter = m_classA->getInterface(objectKey);
if (myInter)
myInter->executeMethod(methodKey);
Looks like a good case for a Mediator Pattern.
This pattern manage communication between 2 objects that he owns.
I'm writing a piece of generic software that will be loaded on to many different variants of the same basic hardware. They all have the same processor, but with different peripherals and their own functions that need to be carried out. The software will know which variant it should run by reading a hardware switch value.
Here's my current implementation in a nutshell:
class MyBase
{
public:
MyBase() { }
virtual run() = 0;
}
class VariantA : public MyBase
{
public:
VariantA () { }
virtual run()
{
// Run code specific to hardware Variant-A
}
}
class VariantB : public MyBase
{
public:
VariantB () { }
virtual run()
{
// Run code specific to hardware Variant-B
}
}
void main()
{
MyBase* variant;
uint_8 switchValue = readSwitchValue();
switch(switchValue)
{
case 0:
variant = new VariantA();
break;
case 1:
variant = new VariantB();
break;
}
variant->run();
}
Now this works just fine. I read the hardware value and use a switch statement to create the new corresponding class.
The problem is that there are a lot of variants I have to deal with. Currently about 15, with the potential to add another 20-30 in the near future. I have really come to despise switch statements that run for hundreds of lines, so I'm really looking for a better way to do this, probably through templates.
I want to be able to use my hardware value to look up a type and use that type to create my new object. Ideally when I add a new variant, I create the new class, add that class type to my lookup table with it's matching hardware value, and it's good to go.
Is this possible at all? What's a good solution here?
As stated, you make a factory, but not necessarily with naive switch statements. What you can do is make a template class to create the relevant object and dynamically add these to your factory.
class VariantinatorBase {
public:
VariantinatorBase() {}
virtual ~VariantinatorBase() {}
virtual std::unique_ptr<Variant> Create() = 0;
};
template< class T >
class Variantinator : public VariantinatorBase {
public:
Variantinator() {}
virtual ~Variantinator() {}
virtual std::unique_ptr<Variant> Create() { return std::make_unique<T>(); }
};
Now you have a class factory that allows you to register these.
class VariantFactory
{
public:
VariantFactory()
{
// If you want, you can do all your Register() calls in here, and even
// make the Register() function private.
}
template< uint8_t type, typename T >
void Register()
{
Register( type, std::make_unique<Variantinator<T>>() );
}
std::unique_ptr<Variant> Create( uint8_t type )
{
TSwitchToVariant::iterator it = m_switchToVariant.find( type );
if( it == m_switchToVariant.end() ) return nullptr;
return it->second->Create();
}
private:
void Register( uint8_t type, std::unique_ptr<VariantinatorBase>&& creator )
{
m_switchToVariant[type] = std::move(creator);
}
typedef std::map<uint8_t, std::unique_ptr<VariantinatorBase> > TSwitchToVariant;
TSwitchToVariant m_switchToVariant;
};
At the beginning of your program, create the factory and register your types:
VariantFactory factory;
factory.Register<0, VariantA>();
factory.Register<1, VariantB>();
factory.Register<2, VariantC>();
Then later, you want to call on it:
std::unique_ptr<Variant> thing = factory.Create( switchValue );
You are looking for a factory
http://www.oodesign.com/factory-pattern.html
A factory is a software module (a method, a class) whose sole purpose is to create the right object for the job. An example using a factory class:
class VariantFactory
{
MyBase* CreateObject(uint_8 value);
}
And the CreateObject method can be filled out to give you the type of object that you need.
In the case of a very small selection of objects with simple construction, a simple switch statement might suffice. As soon as you get a lot of objects or ones that require more detailed construction, a factory is quite useful.
I made this a comment; let's turn it into an answer:
Personally, I think a "switch/case" block to create the appropriate class is probably an optimal solution. Just put your case statement in a static "factory" method that returns a reference to the specific class. IMHO...
Here's a good example: factory method design pattern
Class Book : public Product
{
};
class Computer : public Product
{
};
class ProductFactory
{
public:
virtual Product* Make(int type)
{
switch (type)
{
case 0:
return new Book();
case 1:
return new Computer();
[...]
}
}
}
Call it like this:
ProductFactory factory = ....;
Product* p1 = factory.Make(0); // p1 is a Book*
Product* p2 = factory.Make(1); // p2 is a Computer*
// remember to delete p1 and p2
Note that in his most excellent response, smink also suggests some other design alternatives, too.
BOTTOM LINE: There's nothing inherently "wrong" with a switch/case block. Even for a switch with many case options.
IMHO...
PS:
This really isn't creating a "dynamic type". Rather, it's "creating a static type dynamically". That would be equally true if you used a template or an enum solution as well. But again - I vastly prefer the "switch/case".
Update: I am leaving my original solution here for posterity, but consider the solution provided by paddy to be superior and less error prone. With only a couple of slight improvements I think it's actually about as good as you can possibly get.
Consider this design:
class VariantA : public MyBase
{
static MyBase *CreateMachineInstance() { return new VariantA; }
};
class VariantB : public MyBase
{
static MyBase *CreateMachineInstance() { return new VariantB; }
};
Now, all you need is an std::map that uses a uint_8 as the key and maps it to a function pointer (returning MyBase). Insert the identifiers in the map (pointing each to the appropriate machine creation function) and then read the code and just use the map to find what machine you're using.
This is loosely based on a concept/pattern called a "factory" but may break slightly if your machine constructors require different arguments or you need to perform additional per-machine initialization/operations - and from what you mention it sounds like you might.
If that's the case, you can still use this pattern but you will have to make some tweaks and rearchitect things a bit but you will end up with something much cleaner and easier to augment and maintain.
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
template<class T,class T1>
class HeroHonda
{
private:
T millage;
T1 *options;
public:
HeroHonda() {
puts("constructed");
options=new T1[20];
strcpy(options,"Good millage,Powerstart");
millage=110;
}
virtual T features() {
cout<<options<<"millage is"<<millage<<endl;
return 1;
}
// virtual T Extrafeatures() = 0;
~HeroHonda() {
cout<<"destructor"<<endl;
delete [] options;
}
};
int main()
{
HeroHonda <int,char> *Ptr=new HeroHonda <int,char>;
Ptr->features();
delete Ptr;
}
Suppose I have a list of classes A, B, C, ... which all inherit from Base.
I get the class name as a string from the user, and I want to instantiate the right class and return a pointer to Base. How would you implement this?
I thought of using a hash-table with the class name as the key, and a function pointer to a function that instantiates the right class and returns a Base *.
However, I think I might be able to use the factory pattern here and make it a lot easier, but I just can't quite remember it well, so I though I'd ask for suggestions.
Here is a generic factory example implementation:
template<class Interface, class KeyT=std::string>
struct Factory {
typedef KeyT Key;
typedef std::auto_ptr<Interface> Type;
typedef Type (*Creator)();
bool define(Key const& key, Creator v) {
// Define key -> v relationship, return whether this is a new key.
return _registry.insert(typename Registry::value_type(key, v)).second;
}
Type create(Key const& key) {
typename Registry::const_iterator i = _registry.find(key);
if (i == _registry.end()) {
throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) +
": key not registered");
}
else return i->second();
}
template<class Base, class Actual>
static
std::auto_ptr<Base> create_func() {
return std::auto_ptr<Base>(new Actual());
}
private:
typedef std::map<Key, Creator> Registry;
Registry _registry;
};
This is not meant to be the best in every circumstance, but it is intended to be a first approximation and a more useful default than manually implementing the type of function stijn mentioned. How each hierarchy should register itself isn't mandated by Factory, but you may like the method gf mentioned (it's simple, clear, and very useful, and yes, this overcomes the inherent problems with macros in this case).
Here's a simple example of the factory:
struct Base {
typedef ::Factory<Base> Factory;
virtual ~Base() {}
virtual int answer() const = 0;
static Factory::Type create(Factory::Key const& name) {
return _factory.create(name);
}
template<class Derived>
static void define(Factory::Key const& name) {
bool new_key = _factory.define(name,
&Factory::template create_func<Base, Derived>);
if (not new_key) {
throw std::logic_error(std::string(__PRETTY_FUNCTION__) +
": name already registered");
}
}
private:
static Factory _factory;
};
Base::Factory Base::_factory;
struct A : Base {
virtual int answer() const { return 42; }
};
int main() {
Base::define<A>("A");
assert(Base::create("A")->answer() == 42);
return 0;
}
the quickest yet very usable way in a lot of areas, would be something like
Base* MyFactoryMethod( const std::string& sClass ) const
{
if( sClass == "A" )
return CreateNewA();
else if( sClass == "B" )
return new CreateClassB();
//....
return 0;
}
A* CreateClassA() const
{
return new A();
}
You could also look into the Boost class factory implementation.
If there's only a few derived classes you can use an "if, else" list.
If you plan to have many derived classes it's better to sort out the class registration process (as Georg mentioned) than to use an "if, else" list.
Here's a simple example using the Boost factory method and class registration:
typedef boost::function<Parent*()> factory;
// ...
std::map<std::string, factory> factories;
// Register derived classes
factories["Child1"] = boost::factory<Child1*>();
factories["Child2"] = boost::factory<Child2*>();
// ...
// Instantiate chosen derived class
auto_ptr<Parent> pChild = auto_ptr<Parent>(factories["Child1"]());
First off, yes, that is just what the factory pattern is for.
(By the way, your other idea is a possible implementation of the factory pattern)
If you intend to do this for a large project (if not, just go with stijns answer), you might want to consider using an associative container somewhere instead of explicit branching and maybe even moving the registration responsibility into the classes to
avoid code changes in one additional place (your factory)
and in turn avoid possibly very long recompilation times (for in-header-implementations) when adding a class
To achieve convenient registration in the classes you could use something like this suggestion and add a function pointer or a functor to the entries that instantiates the derived class and returns a pointer to the base.
If you're not afraid of macros you can then add classes to the factory by just adding one tiny macro to its declaration.