Register an Object Creator in Object Factory

Register an object creator in object factory

So you want to put variables definitions in header file? There is a portable way: static variables of template classes. So we get:

template <typename T, typename I>
struct AutoRegister: public I
{
// a constructor which use ourRegisterer so that it is instantiated;
// problem catched by bocco
AutoRegister() { &ourRegisterer; }
private:
static RegisterClass<T, I> ourRegisterer;
};

template <typename T, typename I>
RegisterClass<T, I> AutoRegister<T, I>::ourRegisterer;

class Foo: AutoRegister<Foo, IFoo>
{
public:
virtual void Do();
};

Note that I've kept the inheritance of IFoo non virtual. If there is any risk of inheriting from that class multiple times, it should be virtual.

automatic registration of object creator function with a macro

I find your concept pretty complicated and I'm not sure if it's required. From my point of view your problem can be circumvented when adding the following code:

#include <iostream>
#include <map>
#include <string>

struct Object{}; // Value Object

// provide a simple create function to derived classes
template<class T> struct ObjectT : public Object {

static Object* create() { return new T(); }
};

struct ObjectFactory {

std::map<std::string, Object* (*)()> creators_factory;

static ObjectFactory* instance()
{
static ObjectFactory* __self = NULL;
if (__self == NULL)
__self = new ObjectFactory();

return __self;

}

template <class T> bool reg(const std::string& id, Object* (*creator)() )
{
creators_factory[id] = creator;
return true;
}

// pass in creator function pointer to register it to id
static Object* create(const std::string& id) {
return instance()->creators_factory[id]();
}

};

#define REGISTER_CHAIN(T) bool isRegistered_##T = ObjectFactory::instance()->reg<T>(#T, T::create)

struct DerivedA : public ObjectT<DerivedA> { DerivedA() { std::cout << "DerivedA constructor\n"; } };
REGISTER_CHAIN(DerivedA);

struct DerivedB : public ObjectT<DerivedB> { DerivedB() { std::cout << "DerivedB constructor\n"; } };
REGISTER_CHAIN(DerivedB);

struct DerivedC : public ObjectT<DerivedC> { DerivedC() { std::cout << "DerivedC constructor\n"; } };
REGISTER_CHAIN(DerivedC);

struct DerivedD : public ObjectT<DerivedD> { DerivedD() { std::cout << "DerivedD constructor\n"; } };
REGISTER_CHAIN(DerivedD);

int main(void)
{
// Call last link in the register chain to register all object creators
//ObjectFactory::Register<LAST_CHAIN_LINK>::chain();
delete ObjectFactory::create("DerivedA");
delete ObjectFactory::create("DerivedB");
delete ObjectFactory::create("DerivedC");
delete ObjectFactory::create("DerivedD");
return 0;
}

I hope this helps.

Best regards,
Martin

Custom Object Factory

I think the problem here is combining the following two requirements:

  1. You want to use the quite simple function void CreateNode(int) to create any node.
  2. You want the user to be able to create new nodes derived from Node and use your factory to create them.

Now what I would suggest is something similar to R Sahu however without following the Factory pattern as strictly as he did.

You could get the functionality you seek by requiring your users to pass a small Creator-object to your factory. (Note that this is deviating a bit from the classical Factory-pattern. As you basically make your NodeFactory into a delegator using the creator-classes.)

class NodeCreator {
public:
virtual Node* create(int) = 0;
virtual ~NodeCreator() = default;
};

class DefaultNodeCreator : public NodeCreator {
public:
virtual Node* create(int value) {
return new Node(value);
}
};

Now I as a user will create my own node:

class MyNode : public Node {
private:
int otherValue;
public:
MyNode(int nodeValue, int otherValue )
: Node(nodeValue), otherValue(otherValue)
{}
// Implement other functionality...
};

class MyNodeCreator : public NodeCreator { 
private:
// I added otherNodeValue to show that Creators can have a state.
int otherNodeValue;
public:
MyNodeCreator(int otherNodeValue ) : otherNodeValue(otherNodeValue) {}
virtual Node* create(int value) {
return new MyNode(value, otherNodeValue);
}
};

Now finally in your Factory class you need to set it like this:

class NodeFactory
{
std::vector<Node*> Nodes;
std::unique_ptr<NodeCreator> activeCreator;

public:
NodeFactory() {
setNodeCreator(nullptr);
}

void createNode(int Value)
{
Nodes.push_back( activeCreator->create(Value) );
}

void setNodeCreator( std::unique_ptr<NodeCreator> creator ) {
if (creator == nullptr) {
activeCreator.reset( new DefaultNodeCreator() );
else {
activeCreator.reset(creator);
}
}
};

To use it from main:

int main() {
NodeFactory nf;

nf.createNode(1); // Creating Node(1)
nf.createNode(2); // Creating Node(2)

nf.setCreator( new MyNodeCreator(5) );
// Any nodes created now will be of type MyNode
// with otherNodeValue == 5.

nf.createNode(2); // Creating MyNode(2, 5)
nf.createNode(3); // Creating MyNode(3, 5)
}

A final note:

If you intend for your users to implement subclasses of Node and use these with polymorphism as shown above, it is important that you declare Node's destructor as virtual. You have no guarantee that your users will not use dynamic allocation in their subclasses, so it is your responsibility to ensure that their destructors get called.

Factory pattern in C#: How to ensure an object instance can only be created by a factory class?

Looks like you just want to run some business logic before creating the object - so why dont you just create a static method inside the "BusinessClass" that does all the dirty "myProperty" checking work, and make the constructor private?

public BusinessClass
{
public string MyProperty { get; private set; }

private BusinessClass()
{
}

private BusinessClass(string myProperty)
{
MyProperty = myProperty;
}

public static BusinessClass CreateObject(string myProperty)
{
// Perform some check on myProperty

if (/* all ok */)
return new BusinessClass(myProperty);

return null;
}
}

Calling it would be pretty straightforward:

BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);

How to design a simple C++ object factory?

I think there are two separate problems here.

One problem is: how does TheManager name the class that it has to create? It must keep some kind of pointer to "a way to create the class". Possible solutions are:

  • keeping a separate pointer for each kind of class, with a way to set it, but you already said that you don't like this as it violates the DRY principle
  • keeping some sort of table where the key is an enum or a string; in this case the setter is a single function with parameters (of course if the key is an enum you can use a vector instead of a map)

The other problem is: what is this "way to create a class"? Unfortunately we can't store pointers to constructors directly, but we can:

  • create, as others have pointed out, a factory for each class
  • just add a static "create" function for each class; if they keep a consistent signature, you can just use their pointers to functions

Templates can help in avoiding unnecessary code duplication in both cases.

How to implement the factory method pattern in C++ correctly

First of all, there are cases when
object construction is a task complex
enough to justify its extraction to
another class.

I believe this point is incorrect. The complexity doesn't really matter. The relevance is what does. If an object can be constructed in one step (not like in the builder pattern), the constructor is the right place to do it. If you really need another class to perform the job, then it should be a helper class that is used from the constructor anyway.

Vec2(float x, float y);
Vec2(float angle, float magnitude); // not a valid overload!

There is an easy workaround for this:

struct Cartesian {
inline Cartesian(float x, float y): x(x), y(y) {}
float x, y;
};
struct Polar {
inline Polar(float angle, float magnitude): angle(angle), magnitude(magnitude) {}
float angle, magnitude;
};
Vec2(const Cartesian &cartesian);
Vec2(const Polar &polar);

The only disadvantage is that it looks a bit verbose:

Vec2 v2(Vec2::Cartesian(3.0f, 4.0f));

But the good thing is that you can immediately see what coordinate type you're using, and at the same time you don't have to worry about copying. If you want copying, and it's expensive (as proven by profiling, of course), you may wish to use something like Qt's shared classes to avoid copying overhead.

As for the allocation type, the main reason to use the factory pattern is usually polymorphism. Constructors can't be virtual, and even if they could, it wouldn't make much sense. When using static or stack allocation, you can't create objects in a polymorphic way because the compiler needs to know the exact size. So it works only with pointers and references. And returning a reference from a factory doesn't work too, because while an object technically can be deleted by reference, it could be rather confusing and bug-prone, see Is the practice of returning a C++ reference variable, evil? for example. So pointers are the only thing that's left, and that includes smart pointers too. In other words, factories are most useful when used with dynamic allocation, so you can do things like this:

class Abstract {
public:
virtual void do() = 0;
};

class Factory {
public:
Abstract *create();
};

Factory f;
Abstract *a = f.create();
a->do();

In other cases, factories just help to solve minor problems like those with overloads you have mentioned. It would be nice if it was possible to use them in a uniform way, but it doesn't hurt much that it is probably impossible.



Related Topics



Leave a reply



Submit