Design question about create factory method.
Hi all,
Sorry for the dumb topic name. I didn´t know what exaplanation to use for the topic :).
Well, I would like someone to have a look at a problem I have found several times and couldn´t been able to found a satisfying solution.
Think for example of a factory template to create objects of a class, that have a Create method. We can have something like this:
template <class _T>
class CFactory : public CSingleton < CFactory>
{
_T* Create()=0;
....
}
The problem is that every object we create may have a different signature depending on its type, for this I got some solutions, but I´m not pretty happy with them:
1) Having a param list in the create function:
template <class _T>
class CFactory : public CSingleton < CFactory>
{
_T* Create(ParamList)=0;
....
}
this way all methods will have same signature and the only thing we will have is to rewrite them in child clases. This is somehow a radical decision for me.
2) Not have the Create in the generic class and move it to the children. Ummm, this will work but, I don´t have anything forcing/telling me to write the Create functions in child clases, well thet compiler will claims that it can found the method in the class if I try to call it, but seems dirty to me.
if would be something like this:
class CFactory : public CSingleton < CFactory>
{
....
}
class ParticularFactory : public CFactory
{
ParticularObject* Create( Particular creationg signature) { ... }
}
So, has anybody found in the same situation and did find a better solution?.
Thanks in advance,
notbad.
A factory is a black box. You feed it the key, it returns the instance.
If you need to know which type you want before you call the factory (constructor args), then you cannot use factory - at very least it won't be clean.
If you need to define in advance which parameters you need, then you don't need the factory. The whole point of a factory is that you can replace implementations return at any point (in extreme cases via run-time class instantiation and reflection).
For example - let's say your factory makes Widgets. You want it to create a widget named "ListBox". If you later replace that with "Tree", nothing changes. Or better yet, you create a widget from a string. This string will be obtained from some configuration file and may change at any point - how will you know which parameters to pass it?
The only suitable way is to provide the factory with some configuration object, which the *newly created* instance can query for parameters.
For certain types of tasks, I choose one such object. For example, when creating messages from network, I pass the Buffer into factory. Factory then reads the message ID, instantiates the proper object, and passes remaining buffer to constructor of that message, which reads relevant fields.
The only one that knows about the contents is the message itself. Neither the factory nor the user know how to populate it.
Example:
If you need to know which type you want before you call the factory (constructor args), then you cannot use factory - at very least it won't be clean.
If you need to define in advance which parameters you need, then you don't need the factory. The whole point of a factory is that you can replace implementations return at any point (in extreme cases via run-time class instantiation and reflection).
For example - let's say your factory makes Widgets. You want it to create a widget named "ListBox". If you later replace that with "Tree", nothing changes. Or better yet, you create a widget from a string. This string will be obtained from some configuration file and may change at any point - how will you know which parameters to pass it?
The only suitable way is to provide the factory with some configuration object, which the *newly created* instance can query for parameters.
For certain types of tasks, I choose one such object. For example, when creating messages from network, I pass the Buffer into factory. Factory then reads the message ID, instantiates the proper object, and passes remaining buffer to constructor of that message, which reads relevant fields.
The only one that knows about the contents is the message itself. Neither the factory nor the user know how to populate it.
Example:
void onReceive( Buffer *buf ){ Message *msg = factory.createInstance(buf); msg->dispatch(target);}Message * Factory::createInstance(Buffer *buf){ switch (buf->readId()) { case ... case ... : return new SomeMessage(buf); }}SomeMessage::SomeMessage(Buffer *buf) : someField(buf->readString()) , anotherField(buf->readInt()) , andAnother(buf->readFloat();{}
Well, this seems pretty the same that the Param List option I exposed. But params are packed in a string, don´t you think?.
notbad.
notbad.
Quote:Well, this seems pretty the same that the Param List option I exposed. But params are packed in a string, don´t you think?.
I do no think so no, the factory is using the buffer to exstract the key not the class using it as parameters. In addition I also do not like the requirement of the clone/ create function when there is not a need for it.
I personally like using a method like:
http://www.liamdevine.co.uk/code/abstract_factory.php
Quote:Original post by notbad
Well, this seems pretty the same that the Param List option I exposed. But params are packed in a string, don´t you think?.
The important question is: Who populates the Param List?
It's the problem of encoding or signature, but where do the parameters come from?
In XML reader, you'd pass the DOM node to factory. Factory would then instantiate whatever object is needed by passing it the child DOM nodes, which in turn would call factory as needed.
The important thing is, neither you nor the factory have any knowledge of what the parameters are, nor may they be dependent on the type of object being instantiated, unless that instance is implied by the parameters themselves.
Well Antheus, for me, factory should return an initialized instance of the type I asked for. So, I need the type of object to construct, and I know what params will be used, so I will be populating the list.
notbad.
notbad.
Quote:Original post by notbad
Well Antheus, for me, factory should return an initialized instance of the type I asked for. So, I need the type of object to construct, and I know what params will be used, so I will be populating the list.
In that case you don't need a factory, just create the instances. By reverting to factory pattern, you're merely creating another redundant abstraction.
Factories are used when you don't know which object you'll be creating.
Think of it this way: implementation of a proper factory can, at any given time, be replaced. Either with no members, with new members, or by changing existing members - yet the code that depends on it doesn't change, in cases of platforms that support it - it can be done during run-time, requiring no recompilation of the rest of application.
If you know not only the type of object to create, but parameters to pass to it, just do it directly - factory won't do its primary function, which is to serve as an abstraction.
This is analogous to asking the type of polymorphic classes. If you need to know of which type a certain instance is, there's something wrong with design, and introduces coupling which polymorphism should prevent.
I see... So I should be going with the "moving create method to child classes", Or just forgetting about a base class that will be inherited from child, and write final classes directly, am I ok? I just was trying to use the factory thing to reuse code, because base class will have a base structure I would like to spread through children. So, I´m left only with the first method (create method only in children), do you think it is ok?.
Note: Thanks a lot for the fast asnwers.
notbad.
Note: Thanks a lot for the fast asnwers.
notbad.
Quote:"moving create method to child classes"
I don't quite get this.
A factory is a single method/function, which takes a key, and returns an instance of an object:
BaseType *create(int key){ switch (key) { case 0 : return new Foo(); case 1 : return new Bar(); case 2 : return new FooBar(); } return NULL;}
There are various ways to make this more elaborate, but classes returned know nothing of factory, not even that this is how they are instantiated.
Depending on language, there are obviously variations on that, more or less elaborate, but if you're introducing factory-related methods into classes returned by factory there's usually something wrong.
There really is nothing more about factories than a single method. No need for singletons or anything as such. Unless you have dynamic factories, what does it matter how many instances there are. They hold no state.
If you're tempted to use some form of auto-registration, I'd suggest against it. C++ isn't good for that, and you'll run into problems, no matter how you try to enforce the single instance.
Look into the link provided above which demonstrates abstract factories. Then, at start, explicitly register the instances you want returned. There's also a more comprehensive overview at codeproject.
Yes, I understood that part (the factory one), they are used to instantiate just objects, they don´t know anything about the nature of the object it instantiates , just instantation is its duty.
Ok, but now think on a system like this:
System
{
...Logic and data...
}
I will have some types of systems that I want to be "factories" for its own type of objects:
RenderSytem
{
RenderObject* Create( MeshFile, ...);
}
IASystem
{
IAObject* Create(Script);
}
What I was asking before was if a good solution to reuse the logic/data of System in children subsystems (RenderSystem, IASystem), coudl be to move the Create methods to children classes, this way, in this classes I really know what params an RenderObject or a IAObject will use to initialize, and I still have all functionality/data inherited from parent.
Thanks in advance, and sorry for the long post,
notbad.
Ok, but now think on a system like this:
System
{
...Logic and data...
}
I will have some types of systems that I want to be "factories" for its own type of objects:
RenderSytem
{
RenderObject* Create( MeshFile, ...);
}
IASystem
{
IAObject* Create(Script);
}
What I was asking before was if a good solution to reuse the logic/data of System in children subsystems (RenderSystem, IASystem), coudl be to move the Create methods to children classes, this way, in this classes I really know what params an RenderObject or a IAObject will use to initialize, and I still have all functionality/data inherited from parent.
Thanks in advance, and sorry for the long post,
notbad.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement