Jump to content
  • Advertisement
Sign in to follow this  
notbad

Design question about create factory method.

This topic is 3971 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

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.

Share this post


Link to post
Share on other sites
Advertisement
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:

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();
{}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!