Archived

This topic is now archived and is closed to further replies.

safe abstract factory?

This topic is 4955 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! I''m having a little problem with my design. The thing is that I want to have an abstract factory that creates different types of objects. But, I don''t just want my factory to create objects on request. Instead of a function like this: void* create(id); I want to have something like this: void QueryInterface(ID id, T** pInterface); And before the object connected to the "id" is created, I want to check if it supports the "pInterface" of type T. So, so far I have only a ICreator object saved in my factory together with an ID. class ICreator { public: void* create() = 0; }; template class Creator { void* create() { return new T; } }; And for eg, these entrys in the factory: (must save the creator as a ICreator, or otherwise I cant store them in the same std::map) ("GLRenderer", (ICreator)Creator) ("DXRenderer", (ICreator)Creator) And it works just fine if I hard code the factory implementation, since then the QueryInterface function isn''t virtual and therefor can be a template function. But the problem is that I want to have an INTERFACE for the factory. And when making a function virtual it can''t be a template function Something like this: class IFactory { public: template virtual void QueryInterface(ID id, T** pInterface); virtual void AddType(ID id, ICreator* pCreator); }; Which isn''t possible, since template functions can''t be virtual. So, the thing is that I don''t want the objects to be created if they don''t support the passed interface pInterface. Has anyone done something like this and could give me some hints? thank you !

Share this post


Link to post
Share on other sites
What about changing it to a template class, you can have virtual methods in a template class instead of template member function you could do something like so:


template<class i_type>
class IFactory {
public:
typedef i_type interface_type;
virtual void QueryInterface(ID id, interface_type** pInterface) = 0;
virtual void AddType(ID id, ICreator* pCreator) = 0;
virtual ~IFactory() {}
protected:
IFactory() {}
};


[edited by - snk_kid on May 20, 2004 12:10:39 PM]

Share this post


Link to post
Share on other sites
Yes, I have tried that version too. But then I can''t store factory''s in a std::vector / std::map which is essential for mes since I''m planning to have a SystemManager class like:

class ISystemManager {
public:
virtual void QueryInterface(ID id, T** pInterface);
virtual void AddFactory(ID id, IFactory pFactory);
};

//The same proble arises here as well, where I need the type of pInterface.

This class must be able to store all factorys that are plugged to it. And then when a new module is loaded I just send over a ISystemManager class which will let the new module to have access to all other available modules.

This way a module which loads a submodule may send over a custom made ISystemManager to the submodule only letting it access a restricted amount of modules.

class Plugin {
virtual void Connect(ISystemManager* pSystems) = 0;
};

But still, first I would need to fix the problem described above, which currently I''m not sure how to solve

Share this post


Link to post
Share on other sites
They only thing i can think of if you have another Interface type at the top of the interface hierarchy that all other interfaces extend just like IUnknown (conceptually) in COM.


class Interface {
public:
virtual void do_it() = 0;
virtual IUnknown() {}
protected:
IUnknown() {}
};

class IFactory {
public:
template
virtual void QueryInterface(ID id, Interface** pInterface);
virtual void AddType(ID id, ICreator* pCreator);
};


[edited by - snk_kid on May 20, 2004 1:01:02 PM]

Share this post


Link to post
Share on other sites
Hey, seems like it works great with this:


class POINTER_TYPE {
public:
template <class T>
POINTER_TYPE(T** pInterface) {
m_cast_safe_pointer = new INTERFACE_INFO<T>();
m_interface_pointer = pInterface;
};

template <class T>
bool compatibleInterface(T* pInterface) {
return (dynamic_cast<INTERFACE_INFO<T>*>(m_cast_safe_pointer));
}

template <class T>
bool setPointer(T* pImpl) {
if(compatibleInterface(pImpl))
return (*m_interface_pointer = pImpl);
else
return 0;
}
private:
class INTERFACE_INFO_BASE {
private:
virtual void dummy() {}
};

template <class T>
class INTERFACE_INFO : public INTERFACE_INFO_BASE {
private:
};

INTERFACE_INFO_BASE* m_cast_safe_pointer;
void** m_interface_pointer;
};




then I replace QueryInterface in the ISystemManager with :
virtual void QueryInterface(ID id, POINTER_TYPE pInterface) = 0;

and then also in the IFactory :
virtual void QueryInterface(ID id, POINTER_TYPE pInterface) = 0;

Then I can use it like this:

IRenderer* pRenderer = 0;
pSystemManager->QueryInterface("GL_RENDERER", (IRenderer**)&pRenderer);


The ISystemManager can for eg be implemented by iterating through the std::map with IFacotrys and on each of them call the QueryInterface(id,pInterface);

And the IFactory points to a Factory which knows about its own type, so the implementation on the QueryInterface in the Factory will be like:

template
class Factory {
public:
void QueryInterface(ID id, POINTER_TYPE pInterface) {
pInterface.compatibleInterface(static_cast(0));
//And if that succedes, then we call the create() function!
}
};

Now that will only create the objects from the factory if the given interface to the POINTER_TYPE is compatible

Share this post


Link to post
Share on other sites
So far it works all right...

Though haven''t tested it that much... but rather only with simple interface differences, havent tested interfaces that derive from same base etc...

Share this post


Link to post
Share on other sites