I've written a class with the following static method:
MyMap& Manager::GetMap( void )
{
static MyMap* factories = new MyMap();
return ( *factories );
}
Where "MyMap" is a typedef for:
unordered_map<string, function<Base* ( Dependency& d )>>
There are also a variety of types derived from Base e.g.
class Derived1 : public Base
{
public:
Derived1( Dependency& d );
};
Consider the following usage.
I define the following in an implementation file for Derived1:
#include "Derived1.h"
#include "Manager.h"
int RegisterDerived1( void )
{
Manager::GetMap()["Test"] = []( Dependency& d ){ return new Derived1( d ); };
return 0;
}
int Reg = RegisterDerived1();
You can't call functions at file scope, but you can assign the return value of a function to a global variable even if that function has side effects. Hence, by the time that "Manager" is in use the "MyMap" will contain string/function pairs for various derived types of "Base" (so far). The intent is that new derived types of "Base" register themselves with "Manager", able to construct instances of that type and select which type based on a name.
I'm wondering if this represents safe behaviour and/or if there are alternative implementations to get the desired effect?
I've been made aware of this article that proposes a generic registration object that takes the above pair in its constructor and does the registering, a static instance of which is then defined for each class to be registered.
http://accu.org/index.php/journals/597
The principle is fine.
A few things you may want to consider:
returning raw pointers is a bad idea - use unique_ptr instead.
Did you really want the Dependency& reference to be non-const?
Hide the internal implementation. There's no need for users to know (or care) that it's an unordered_map.
A slightly modified version with inline comments for you to consider:
#include <functional>
#include <unordered_map>
#include <memory>
#include <string>
struct Base
{
virtual ~Base() = default;
};
struct Dependency
{
};
struct Manager
{
// I notice that Depdendency& is not const. Was that what you wanted?
using factory_function = std::function<std::unique_ptr<Base> ( Dependency& d )>;
// public registration function hides internal implementation of map
static bool register_function(const std::string ident, factory_function f)
{
return GetMap().emplace(std::move(ident), std::move(f)).second;
}
// public create function hides internal implementation of map
// returns a unique_ptr - much better!
static std::unique_ptr<Base> create(const std::string& ident, Dependency& d)
{
// this will throw an exception if the factory does not exist.
// another implementation could substitute a known version of Base,
// for example. But now it's under your control and the user does
// not have to think about it.
return GetMap().at(ident)(d);
}
private:
using MyMap = std::unordered_map<std::string, factory_function>;
// private map implementation. In future we may want to add a mutex
// (in case the map can be dynamically updated?)
// so let's encapsulate
static MyMap& GetMap()
{
// no need for new here. Static variables are cleanly destructed at
// the end of the program, and initialised the first time the code
// flows over them.
static MyMap _map;
return _map;
}
};
struct Derived1 : Base
{
Derived1(Dependency&) {}
};
// now we don't need to care about Manager's implementation.
// this is better - we are decoupled.
bool derived1_registered = Manager::register_function("Derived1",
[](Dependency& d)
{
return std::make_unique<Derived1>(d);
});
int main()
{
Dependency d;
auto p = Manager::create("Derived1", d);
return 0;
}
I am looking for an intuitive and extensible way to implement factories for subclasses of a given base class in c++. I want to provide such a factory function in a library.The tricky part is that I want said factory to work for user-defined subclasses as well (e.g. having the library's factory function build different subclasses depending on what modules are linked to it). The goal is to have minimal burden/confusion for downstream developers to use the factories.
An example of what I want to do is: given a std::istream, construct and return an object of whatever subclass matches the content, or a null pointer if no matches are found. The global factory would have a signature like:
Base* Factory(std::istream &is){ ... };
I am familiar with prototype factories, but I prefer to avoid the need to make/store prototype objects. A related question is posted here for java: Allowing maximal flexibly/extensibility using a factory.
I am not looking for c++11-specific solutions at the moment, but if they are more elegant I would be happy to learn about those.
I came up with one working solution which I believe is fairly elegant, which I will post as an answer. I can imagine this problem to be fairly common, so I am wondering if anyone knows of better approaches.
EDIT: it seems some clarification is in order...
The idea is for the factory to construct an object of a derived class, without containing the logic to decide which one. To make matters worse, the factory method will end up as part of a library and derived classes may be defined in plugins.
Derived classes must be able to decide for themselves whether or not they are fit for construction, based on the input provided (for example an input file). This decision can be implemented as a predicate that can be used by the factory, as was suggested by several people (great suggestion, by the way!).
If I understand this correctly, we want a factory function that can select which derived class to instantiate based on constructor inputs. This is the most generic solution that I could come up with so far. You specify mapping inputs to organize factory functions, and then you can specify constructor inputs upon factory invocation. I hate to say that the code explains more than I could in words, however I think the example implementations of FactoryGen.h in Base.h and Derived.h are clear enough with the help of comments. I can provide more details if necessary.
FactoryGen.h
#pragma once
#include <map>
#include <tuple>
#include <typeinfo>
//C++11 typename aliasing, doesn't work in visual studio though...
/*
template<typename Base>
using FactoryGen<Base> = FactoryGen<Base,void>;
*/
//Assign unique ids to all classes within this map. Better than typeid(class).hash_code() since there is no computation during run-time.
size_t __CLASS_UID = 0;
template<typename T>
inline size_t __GET_CLASS_UID(){
static const size_t id = __CLASS_UID++;
return id;
}
//These are the common code snippets from the factories and their specializations.
template<typename Base>
struct FactoryGenCommon{
typedef std::pair<void*,size_t> Factory; //A factory is a function pointer and its unique type identifier
//Generates the function pointer type so that I don't have stupid looking typedefs everywhere
template<typename... InArgs>
struct FPInfo{ //stands for "Function Pointer Information"
typedef Base* (*Type)(InArgs...);
};
//Check to see if a Factory is not null and matches it's signature (helps make sure a factory actually takes the specified inputs)
template<typename... InArgs>
static bool isValid(const Factory& factory){
auto maker = factory.first;
if(maker==nullptr) return false;
//we have to check if the Factory will take those inArgs
auto type = factory.second;
auto intype = __GET_CLASS_UID<FPInfo<InArgs...>>();
if(intype != type) return false;
return true;
}
};
//template inputs are the Base type for which the factory returns, and the Args... that will determine how the function pointers are indexed.
template<typename Base, typename... Args>
struct FactoryGen : FactoryGenCommon<Base>{
typedef std::tuple<Args...> Tuple;
typedef std::map<Tuple,Factory> Map; //the Args... are keys to a map of function pointers
inline static Map& get(){
static Map factoryMap;
return factoryMap;
}
template<typename... InArgs>
static void add(void* factory, const Args&... args){
Tuple selTuple = std::make_tuple(args...); //selTuple means Selecting Tuple. This Tuple is the key to the map that gives us a function pointer
get()[selTuple] = Factory(factory,__GET_CLASS_UID<FPInfo<InArgs...>>());
}
template<typename... InArgs>
static Base* make(const Args&... args, const InArgs&... inArgs){
Factory factory = get()[std::make_tuple(args...)];
if(!isValid<InArgs...>(factory)) return nullptr;
return ((FPInfo<InArgs...>::Type)factory.first) (inArgs...);
}
};
//Specialize for factories with no selection mapping
template<typename Base>
struct FactoryGen<Base,void> : FactoryGenCommon<Base>{
inline static Factory& get(){
static Factory factory;
return factory;
}
template<typename... InArgs>
static void add(void* factory){
get() = Factory(factory,__GET_CLASS_UID<FPInfo<InArgs...>>());
}
template<typename... InArgs>
static Base* make(const InArgs&... inArgs){
Factory factory = get();
if(!isValid<InArgs...>(factory)) return nullptr;
return ((FPInfo<InArgs...>::Type)factory.first) (inArgs...);
}
};
//this calls the function "initialize()" function to register each class ONCE with the respective factory (even if a class tries to initialize multiple times)
//this step can probably be circumvented, but I'm not totally sure how
template <class T>
class RegisterInit {
int& count(void) { static int x = 0; return x; } //counts the number of callers per derived
public:
RegisterInit(void) {
if ((count())++ == 0) { //only initialize on the first caller of that class T
T::initialize();
}
}
};
Base.h
#pragma once
#include <map>
#include <string>
#include <iostream>
#include "Procedure.h"
#include "FactoryGen.h"
class Base {
public:
static Base* makeBase(){ return new Base; }
static void initialize(){ FactoryGen<Base,void>::add(Base::makeBase); } //we want this to be the default mapping, specify that it takes void inputs
virtual void speak(){ std::cout << "Base" << std::endl; }
};
RegisterInit<Base> __Base; //calls initialize for Base
Derived.h
#pragma once
#include "Base.h"
class Derived0 : public Base {
private:
std::string speakStr;
public:
Derived0(std::string sayThis){ speakStr=sayThis; }
static Base* make(std::string sayThis){ return new Derived0(sayThis); }
static void initialize(){ FactoryGen<Base,int>::add<std::string>(Derived0::make,0); } //we map to this subclass via int with 0, but specify that it takes a string input
virtual void speak(){ std::cout << speakStr << std::endl; }
};
RegisterInit<Derived0> __d0init; //calls initialize() for Derived0
class Derived1 : public Base {
private:
std::string speakStr;
public:
Derived1(std::string sayThis){ speakStr=sayThis; }
static Base* make(std::string sayThat){ return new Derived0(sayThat); }
static void initialize(){ FactoryGen<Base,int>::add<std::string>(Derived0::make,1); } //we map to this subclass via int with 1, but specify that it takes a string input
virtual void speak(){ std::cout << speakStr << std::endl; }
};
RegisterInit<Derived1> __d1init; //calls initialize() for Derived1
Main.cpp
#include <windows.h> //for Sleep()
#include "Base.h"
#include "Derived.h"
using namespace std;
int main(){
Base* b = FactoryGen<Base,void>::make(); //no mapping, no inputs
Base* d0 = FactoryGen<Base,int>::make<string>(0,"Derived0"); //int mapping, string input
Base* d1 = FactoryGen<Base,int>::make<string>(1,"I am Derived1"); //int mapping, string input
b->speak();
d0->speak();
d1->speak();
cout << "Size of Base: " << sizeof(Base) << endl;
cout << "Size of Derived0: " << sizeof(Derived0) << endl;
Sleep(3000); //Windows & Visual Studio, sry
}
I think this is a pretty flexible/extensible factory library. While the code for it is not very intuitive, I think using it is fairly simple. Of course, my view is biased seeing as I'm the one that wrote it, so please let me know if it is the contrary.
EDIT : Cleaned up the FactoryGen.h file. This is probably my last update, however this has been a fun exercise.
My comments were probably not very clear. So here is a C++11 "solution" relying on template meta programming : (Possibly not the nicest way of doing this though)
#include <iostream>
#include <utility>
// Type list stuff: (perhaps use an existing library here)
class EmptyType {};
template<class T1, class T2 = EmptyType>
struct TypeList
{
typedef T1 Head;
typedef T2 Tail;
};
template<class... Etc>
struct MakeTypeList;
template <class Head>
struct MakeTypeList<Head>
{
typedef TypeList<Head> Type;
};
template <class Head, class... Etc>
struct MakeTypeList<Head, Etc...>
{
typedef TypeList<Head, typename MakeTypeList<Etc...>::Type > Type;
};
// Calling produce
template<class TList, class BaseType>
struct Producer;
template<class BaseType>
struct Producer<EmptyType, BaseType>
{
template<class... Args>
static BaseType* Produce(Args... args)
{
return nullptr;
}
};
template<class Head, class Tail, class BaseType>
struct Producer<TypeList<Head, Tail>, BaseType>
{
template<class... Args>
static BaseType* Produce(Args... args)
{
BaseType* b = Head::Produce(args...);
if(b != nullptr)
return b;
return Producer<Tail, BaseType>::Produce(args...);
}
};
// Generic AbstractFactory:
template<class BaseType, class Types>
struct AbstractFactory {
typedef Producer<Types, BaseType> ProducerType;
template<class... Args>
static BaseType* Produce(Args... args)
{
return ProducerType::Produce(args...);
}
};
class Base {}; // Example base class you had
struct Derived0 : public Base { // Example derived class you had
Derived0() = default;
static Base* Produce(int value)
{
if(value == 0)
return new Derived0();
return nullptr;
}
};
struct Derived1 : public Base { // Another example class
Derived1() = default;
static Base* Produce(int value)
{
if(value == 1)
return new Derived1();
return nullptr;
}
};
int main()
{
// This will be our abstract factory type:
typedef AbstractFactory<Base, MakeTypeList<Derived0, Derived1>::Type> Factory;
Base* b1 = Factory::Produce(1);
Base* b0 = Factory::Produce(0);
Base* b2 = Factory::Produce(2);
// As expected b2 is nullptr
std::cout << b0 << ", " << b1 << ", " << b2 << std::endl;
}
Advantages:
No (additional) run-time overhead as you would have with the function pointers.
Works for any base type, and for any number of derived types. You still end up calling the functions of course.
Thanks to variadic templates this works with any number of arguments (giving an incorrect number of arguments will produce a compile-time error message).
Explicit registering of the produce member functions
is not required.
Disadvantages:
All of your derived types must be available when you declare the
Factory type. (You must know what the possible derived types are and they must be complete.)
The produce member functions for the derived types must be public.
Can make compilation slower. (As always the case when relying on template metaprogramming)
In the end, using the prototype design pattern might turn out better. I don't know since I haven't tried using my code.
I'd like to state some additional things (after further discussion on the chat):
Each factory can only return a single object. This seems strange, as the users decide whether they will take the input to create their object or not. I would for that reason suggest your factory can return a collection of objects instead.
Be careful not to overcomplicate things. You want a plugin system, but I don't think you really want factories. I would propose you simply make users register their classes (in their shared object), and that you simply pass the arguments to the classes' Produce (static) member functions. You store the objects if and only if they're not the nullptr.
Update: This answer made the assumption that some kind of magic existed that could be read and passed to the factory, but that's apparently not the case. I'm leaving the answer here because a) I may update it, and b) I like it anyway.
Not hugely different from your own answer, not using C++11 techniques (I've not had a chance to update it yet, or have it return a smart pointer, etc), and not entirely my own work, but this is the factory class I use. Importantly (IMHO) it doesn't call each possible class's methods to find the one that matches - it does this via the map.
#include <map>
// extraneous code has been removed, such as empty constructors, ...
template <typename _Key, typename _Base, typename _Pred = std::less<_Key> >
class Factory {
public:
typedef _Base* (*CreatorFunction) (void);
typedef std::map<_Key, CreatorFunction, _Pred> _mapFactory;
// called statically by all classes that can be created
static _Key Register(_Key idKey, CreatorFunction classCreator) {
get_mapFactory()->insert(std::pair<_Key, CreatorFunction>(idKey, classCreator));
return idKey;
}
// Tries to create instance based on the key
static _Base* Create(_Key idKey) {
_mapFactory::iterator it = get_mapFactory()->find(idKey);
if (it != get_mapFactory()->end()) {
if (it->second) {
return it->second();
}
}
return 0;
}
protected:
static _mapFactory * get_mapFactory() {
static _mapFactory m_sMapFactory;
return &m_sMapFactory;
}
};
To use this you just declare the base-type, and for each class you register it as a static. Note that when you register, the key is returned, so I tend to add this as a member of the class, but it's not necessary, just neat :) ...
// shape.h
// extraneous code has been removed, such as empty constructors, ...
// we also don't technically need the id() method, but it could be handy
// if at a later point you wish to query the type.
class Shape {
public:
virtual std::string id() const = 0;
};
typedef Factory<std::string, Shape> TShapeFactory;
Now we can create a new derived class, and register it as creatable by TShapeFactory...
// cube.h
// extraneous code has been removed, such as empty constructors, ...
class Cube : public Shape {
protected:
static const std::string _id;
public:
static Shape* Create() {return new Cube;}
virtual std::string id() const {return _id;};
};
// cube.cpp
const std::string Cube::_id = TShapeFactory::Register("cube", Cube::Create);
Then we can create a new item based on, in this case, a string:
Shape* a_cube = TShapeFactory::Create("cube");
Shape* a_triangle = TShapeFactory::Create("triangle");
// a_triangle is a null pointer, as we've not registered a "triangle"
The advantage of this method is that if you create a new derived, factory-generatable class, you don't need to change any other code, providing you can see the factory class and derive from the base:
// sphere.h
// extraneous code has been removed, such as empty constructors, ...
class Sphere : public Shape {
protected:
static const std::string _id;
public:
static Shape* Create() {return new Sphere;}
virtual std::string id() const {return _id;};
};
// sphere.cpp
const std::string Sphere::_id = TShapeFactory::Register("sphere", Sphere::Create);
Possible improvements that I'll leave to the reader include adding things like: typedef _Base base_class to Factory, so that when you've declared your custom factory, you can make your classes derive from TShapeFactory::base_class, and so on. The Factory should probably also check if a key already exists, but again... it's left as an exercise.
The best solution I can currently think of is by using a Factory class which stores pointers to producing functions for each derived class. When a new derived class is made, a function pointer to a producing method can be stored in the factory.
Here is some code to illustrate my approach:
#include <iostream>
#include <vector>
class Base{};
// Factory class to produce Base* objects from an int (for simplicity).
// The class uses a list of registered function pointers, which attempt
// to produce a derived class based on the given int.
class Factory{
public:
typedef Base*(*ReadFunPtr)(int);
private:
static vector<ReadFunPtr> registeredFuns;
public:
static void registerPtr(ReadFunPtr ptr){ registeredFuns.push_back(ptr); }
static Base* Produce(int value){
Base *ptr=NULL;
for(vector<ReadFunPtr>::const_iterator I=registeredFuns.begin(),E=registeredFuns.end();I!=E;++I){
ptr=(*I)(value);
if(ptr!=NULL){
return ptr;
}
}
return NULL;
}
};
// initialize vector of funptrs
std::vector<Factory::ReadFunPtr> Factory::registeredFuns=std::vector<Factory::ReadFunPtr>();
// An example Derived class, which can be produced from an int=0.
// The producing method is static to avoid the need for prototype objects.
class Derived : public Base{
private:
static Base* ProduceDerivedFromInt(int value){
if(value==0) return new Derived();
return NULL;
}
public:
Derived(){};
// registrar is a friend because we made the producing function private
// this is not necessary, may be desirable (e.g. encapsulation)
friend class DerivedRegistrar;
};
// Register Derived in the Factory so it will attempt to construct objects.
// This is done by adding the function pointer Derived::ProduceDerivedFromInt
// in the Factory's list of registered functions.
struct DerivedRegistrar{
DerivedRegistrar(){
Factory::registerPtr(&(Derived::ProduceDerivedFromInt));
}
} derivedregistrar;
int main(){
// attempt to produce a Derived object from 1: should fail
Base* test=Factory::Produce(1);
std::cout << test << std::endl; // outputs 0
// attempt to produce a Derived object from 0: works
test=Factory::Produce(0);
std::cout << test << std::endl; // outputs an address
}
TL;DR: in this approach, downstream developers need to implement the producing function of a derived class as a static member function (or a non-member function) and register it in the factory using a simple struct.
This seems simple enough and does not require any prototype objects.
Here is a sustainable idiom for managing factories that resolve at runtime. I've used this in the past to support fairly sophisticated behavior. I favor simplicity and maintainability without giving up much in the way of functionality.
TLDR:
Avoid static initialization in general
Avoid "auto-loading" techniques like the plague
Communicate ownership of objects AND factories
Separate usage and factory management concerns
Using Runtime Factories
Here is the base interface that users of this factory system will interact with. They shouldn't need to worry about the details of the factory.
class BaseObject {
public:
virtual ~BaseObject() {}
};
BaseObject* CreateObjectFromStream(std::istream& is);
As an aside, I would recommend using references, boost::optional, or shared_ptr instead of raw pointers. In a perfect world, the interface should tell me who owns this object. As a user, am I responsible for deleting this pointer when it's given to me? It's painfully clear when it's a shared_ptr.
Implementing Runtime Factories
In another header, put the details of managing the scope of when the factories are active.
class RuntimeFactory {
public:
virtual BaseObject* create(std::istream& is) = 0;
};
void RegisterRuntimeFactory(RuntimeFactory* factory);
void UnregisterRuntimeFactory(RuntimeFactory* factory);
I think the salient point in all of this is that usage is a different concern from how the factories are initialized and used.
We should note that the callers of these free functions own the factories. The registry does not own them.
This isn't strictly necessary, though it offers more control when and where these factories get destroyed. The point where it matters is when you see things like "post-create" or "pre-destroy" calls. Factory methods with these sorts of names are design smells for ownership inversion.
Writing another wrapper around this to manage the factories life-time would be simple enough anyway. It also lends to composition, which is better.
Registering Your New Factory
Write wrappers for each factory registration. I usually put each factory registration in its own header. These headers are usually just two function calls.
void RegisterFooFactory();
void UnregisterFooFactory();
This may seem like overkill, but this sort of diligence keeps your compile times down.
My main then is reduced to a bunch of register and unregister calls.
#include <foo_register.h>
#include <bar_register.h>
int main(int argc, char* argv[]) {
SetupLogging();
SetupRuntimeFactory();
RegisterFooFactory();
RegisterBarFactory();
// do work...
UnregisterFooFactory();
UnregisterBarFactory();
CleanupLogging();
return 0;
}
Avoid Static Init Pitfalls
This specifically avoids objects created during static loading like some of the other solutions. This is not an accident.
The C++ spec won't give you useful assurances about when static loading will occur
You'll get a stack trace when something goes wrong
The code is simple, direct, easy to follow
Implementing the Registry
Implementation details are fairly mundane, as you'd imagine.
class RuntimeFactoryRegistry {
public:
void registerFactory(RuntimeFactory* factory) {
factories.insert(factory);
}
void unregisterFactory(RuntimeFactory* factory) {
factories.erase(factory);
}
BaseObject* create(std::istream& is) {
std::set<RuntimeFactory*>::iterator cur = factories.begin();
std::set<RuntimeFactory*>::iterator end = factories.end();
for (; cur != end; cur++) {
// reset input?
if (BaseObject* obj = (*cur)->create(is)) {
return obj;
}
}
return 0;
}
private:
std::set<RuntimeFactory*> factories;
};
This assumes that all factories are mutually exclusive. Relaxing this assumption is unlikely to result in well-behaving software. I'd probably make stronger claims in person, hehe. Another alternative would be to return a list of objects.
The below implementation is static for simplicity of demonstration. This can be a problem for multi-threaded environments. It doesn't have to be static, nor do I recommend it should or shouldn't be static, it just is here. It isn't really the subject of the discussion, so I'll leave it at that.
These free functions only act as pass-through functions for this implementation. This lets you unit test the registry or reuse it if you were so inclined.
namespace {
static RuntimeFactoryRegistry* registry = 0;
} // anon
void SetupRuntimeFactory() {
registry = new RuntimeFactoryRegistry;
}
void CleanupRuntimeFactory() {
delete registry;
registry = 0;
}
BaseObject* CreateObjectFromStream(std::istream& is) {
return registry->create(is);
}
void RegisterRuntimeFactory(RuntimeFactory* factory) {
registry->registerFactory(factory);
}
void UnregisterRuntimeFactory(RuntimeFactory* factory) {
registry->unregisterFactory(factory);
}
First, there's not really enough detail here to form an opinion, so I'm left to guess. You've provided a challenging question and a minimal solution, but not clarified what is wrong with your solution.
I suspect the complaint centers around the reset back to knowing nothing between a refused construction and the following construction attempts. Given a very large number of potential factories this reset could have us parsing the same data hundreds or thousands of times. If this is the problem the question is this: how do you structure the predicate evaluation phase to limit the amount of work, and allow it to reuse previous parsing results.
I suggest having each factory register with:
1) a factory builder function taking the specialization parameter(s) (iostream in the example)
2) an unordered set of boolean predicates
3) required boolean values of each predicate to allow construction
The set of predicates is used to create/modify the predicate tree. Interior nodes in the tree represent predicates (branching to 'pass', 'fail', and possibly 'don't care'). Both interior nodes and leaves hold constructors which are satisfied if the ancestral predicates are satisfied. As you traverse the tree you first look for constructors at the current level, then evaluate the predicate and follow the required path. If no solution is found along that child path the follow the 'don't care' path.
This allows new factories to share predicate functions. There's probably lots of questions about managing/sorting the tree when the factories go on/off line. There's also the possibility of parser state data that needs to be retained across predicates and reset when construction is completed. There's lots of open questions, but this may work toward addressing the perceived problems with your solution.
TL:DR; Create a graph of predicates to traverse when attempting construction.
Simple solution is just a switch-case:
Base *create(int type, std::string data) {
switch(type) {
case 0: return new Derived1(data);
case 1: return new Derived2(data);
};
}
But then it's just deciding which type you want:
int type_of_obj(string s) {
int type = -1;
if (isderived1(s)) type=0;
if (isderived2(s)) type=1;
return type;
}
Then it's just connecting the two:
Base *create_obj(string s, string data,
Base *(*fptr)(int type, string data),
int (*fptr2)(string s))
{
int type = fptr2(s);
if (type==-1) return 0;
return fptr(type, data);
}
Then it's just registering the function pointers:
class Registry {
public:
void push_back(Base* (*fptr)(int type, string data),
int (*fptr2)(string s));
Base *create(string s, string data);
};
The plugin will have the 2 functions, and the following:
void register_classes(Registry ®) {
reg.push_back(&create, &type_of_obj);
...
}
Plugin loader will dlopen/dlsym the register_classes functions.
(on the other hand, I'm not using this kind of plugins myself because creating new plugins is too much work. I have better way to provide modularity for my program's pieces. What kills plugins is the fact that you need to modify your build system to create new dll's or shared_libs, and doing that is just too much work - ideally new module is just one class; without anything more complicated build system modifications)
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;
}
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.
Let's say I have a class box, and a user can create boxes. How to do it? I understand I create objects by className objectName(args); but how to do it dynamically, depending on the user input?
The correct answer depends on the number of different classes of which you want to create the instances.
If the number is huge (the application should be able to create an instance of any class in your application), you should use the reflection functionality of .Net. But, to be honest, I'm not a big fan of using reflection in business logic, so I would advise not to do this.
I think that in reality you have a limited number on classes for which you want to create instances. And all the other answers make this assumption. What you actually need is a factory pattern. In the next code I also assume that the classes of which you want to create instances, all derive from the same base class, let's say Animal, like this:
class Animal {...};
class Dog : public Animal {...}
class Cat : public Animal {...}
Then create an abstract factory which is an interface that creates an animal:
class IFactory
{
public:
Animal *create() = 0;
};
Then create subclasses for each of the different kinds of animals. E.g. for the Dog class this will become this:
class DogFactory : public IFactory
{
public:
Dog *create() {return new Dog();}
};
And the same for the cat.
The DogFactory::create method overrules the IFactory::create method, even if their return type is different. This is what is called co-variant return types. This is allowed as long as the return type of the subclass's method is a subclass of the return type of the base class.
What you can now do is put instances of all these factories in a map, like this:
typedef std::map<char *,IFactory *> AnimalFactories
AnimalFactories animalFactories;
animalFactories["Dog"] = new DogFactory();
animalFactories["Cat"] = new CatFactory();
After the user input, you have to find the correct factory, and ask it to create the instance of the animal:
AnimalFactories::const_iterator it=animalFactories.find(userinput);
if (it!=animalFactories.end())
{
IFactory *factory = *it;
Animal *animal = factory->create();
...
}
This is the typical abstract factory approach.
There are other approaches as well. When teaching myself C++ I wrote a small CodeProject article about it. You can find it here: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.
Good luck.
The following factory method creates Box instances dynamically based on user input:
class BoxFactory
{
public:
static Box *newBox(const std::string &description)
{
if (description == "pretty big box")
return new PrettyBigBox;
if (description == "small box")
return new SmallBox;
return 0;
}
};
Of course, PrettyBigBox and SmallBox both derive from Box. Have a look at the creational patterns in the C++ design patterns wikibook, as one of them probably applies to your problem.
In C++, it is possible to allocate objects using automatic (stack) and dynamic (heap) storage.
Type variable_name; // variable_name has "automatic" storage.
// it is a local variable and is created on the stack.
Type* pointer_name = NULL; // pointer_name is a "pointer". The pointer, itself,
// is a local variable just like variable_name
// and is also created on the stack. Currently it
// points to NULL.
pointer_name = new DerivedType; // (where DerivedType inherits from Type). Now
// pointer_name points to an object with
// "dynamic" storage that exists on the heap.
delete pointer_name; // The object pointed-to is deallocated.
pointer_name = NULL; // Resetting to NULL prevents dangling-pointer errors.
You can use pointers and heap-allocation to dynamically construct objects as in:
#include <cstdlib>
#include <iostream>
#include <memory>
class Base {
public:
virtual ~Base(){}
virtual void printMe() const = 0;
protected:
Base(){}
};
class Alpha : public Base {
public:
Alpha() {}
virtual ~Alpha() {}
virtual void printMe() const { std::cout << "Alpha" << std::endl; }
};
class Bravo : public Base {
public:
Bravo() {}
virtual ~Bravo() {}
virtual void printMe() const { std::cout << "Bravo" << std::endl; }
};
int main(int argc, char* argv[]) {
std::auto_ptr<Base> pointer; // it is generally better to use boost::unique_ptr,
// but I'll use this in case you aren't familiar
// with Boost so you can get up and running.
std::string which;
std::cout << "Alpha or bravo?" << std::endl;
std::cin >> which;
if (which == "alpha") {
pointer.reset(new Alpha);
} else if (which == "bravo") {
pointer.reset(new Bravo);
} else {
std::cerr << "Must specify \"alpha\" or \"bravo\"" << std::endl;
std::exit(1);
}
pointer->printMe();
return 0;
}
Related: the "Factory" object-oriented design pattern