Factory Design pattern implementation

Please support our C++ advertiser: Intel Parallel Studio Home
Closed Thread

Join Date: Feb 2005
Posts: 5
Reputation: Coding Mage is an unknown quantity at this point 
Solved Threads: 0
Coding Mage Coding Mage is offline Offline
Newbie Poster

Factory Design pattern implementation

 
0
  #1
Feb 10th, 2005
Hi all,

I have an interesting problem for which I already have a solution, but I have a feeling my solution is less than elegant.

I need to create a Factory class which returns an instance of some child of class Foo. Which child is instantiated depends on the value of some integer parameter. So, for example, the following would work well enough:


  1. class FooFactory
  2. {
  3. public:
  4. Foo* getFooInstance( int id );
  5. }
  6.  
  7. Foo* FooFactory::getFooInstance( int id )
  8. {
  9. switch (id) {
  10. case 1:
  11. return new FooBar();
  12. case 2:
  13. return new FooBoo();
  14. default:
  15. return NULL;
  16. }
  17. }
However, I would need to maintain that switch statement everytime I implement a child class of Foo. So, a better solution, I feel, is to register the child class during static initialization:

  1. // FooFactory.h
  2. class FooFactory
  3. {
  4. typedef Foo* (*FooInstantiator)();
  5. typedef std::map<int, FooInstantiator> InstantiatorMap;
  6.  
  7. public:
  8. Foo* getFooInstance( int id );
  9. static int registerFooInstantiator(int id, FooInstantiator func);
  10.  
  11. private:
  12. static InstantiatorMap m_instantiatorMap;
  13. }
  14.  
  15. // FooFactory.cpp
  16. // For the sake of brevity, let's just assume we've guaranteed that
  17. // m_instantiatorMap already has been constructed.
  18. int FooFactory::registerFooInstantiator(int id, FooInstantiator func)
  19. {
  20. m_instantiatorMap.insert( std::make_pair( id, func ) );
  21. return 1;
  22. }
  23.  
  24. // FooBar.h
  25. class FooBar : public Foo
  26. {
  27. ...
  28. static int isInitialized;
  29. ...
  30. }
  31. Foo* getFooBar();
  32.  
  33. // FooBar.cpp
  34. int FooBar::isInitialized =
  35. FooFactory::registerFooInstantiator( 1, getFooBar );
  36.  
  37. Foo* getFooBar() { return new FooBar(); }
The above solution allows me to create a new Foo child class and add it to the factory without having to modify the factory code.

Can I do better? Having to create a getFooXXX() function for each child seems unnecessary. I was thinking of creating a template function getFoo<T>, declared in FooFactory.h, where T would be the child class. This removes the need for separate getFooXXX functions. Any thoughts?
Last edited by Coding Mage; Feb 10th, 2005 at 1:35 pm. Reason: code tags
Quick reply to this message  
Join Date: Feb 2005
Posts: 17
Reputation: kon_t is an unknown quantity at this point 
Solved Threads: 2
kon_t kon_t is offline Offline
Newbie Poster

Re: Factory Design pattern implementation

 
0
  #2
Feb 10th, 2005
You dont specify how you intend to use the factory. That will play a larg part in choosing a Factory pattern to use. So my comments are fairly general.

The motivation behind Factory, is to put the object creation in one place, making maintenance easier & removing dependencies from 'user' code.
IE you expect to change Factory when new Foo sub classes are added. The change can be adding to the switch, or having a heirarchy of Factory classes.


If the Foo heirarchy is fairly stable, then your switch implementation is great.
(I assume that you have left out error checking for simplicity.)
Even if new Foo classes appear fairly often, the code changes are still limited to one place.

Also, if many Foo objects are created, the switch is faster than the map.

In your implementation, you need a new creation function for each class and you also have to provide code which adds the instantiation function/method to the map in Factory. How will you handle errors (eg a duplicate class id)?

In general, i try to avoid passing ids to the object creation code. It can cause maintennace nightmares down the track in anything beyond small projects.
How does user code know which id relates to which sub class?
What would happen (to user code) if a Foo sub class is removed?

And, on a std c++ note.
It is far better to return the newly created objects as auto_ptrs, as these will automatically handle the deletion for you.

eg
auto_ptr<Foo> FooFactory::getFooInstance
Quick reply to this message  
Join Date: Jun 2004
Posts: 436
Reputation: Chainsaw is an unknown quantity at this point 
Solved Threads: 11
Chainsaw's Avatar
Chainsaw Chainsaw is offline Offline
Unprevaricator

Re: Factory Design pattern implementation

 
0
  #3
Feb 10th, 2005
This is sort of a side issue, but I tend to prefer a static method of Foo being the factory, rather than have a seperate class called, in this case, FooFactory. So, the base class would implement
  1. class Foo
  2. {
  3. public:
  4. <blah blah blah>
  5.  
  6. static Foo* Factory(); // or use the auto_ptr<> if you are a fancy 'I don't use old C-style stuff' bit hugger :-)
Quick reply to this message  
Join Date: Feb 2005
Posts: 17
Reputation: kon_t is an unknown quantity at this point 
Solved Threads: 2
kon_t kon_t is offline Offline
Newbie Poster

Re: Factory Design pattern implementation

 
0
  #4
Feb 10th, 2005
Originally Posted by Chainsaw
This is sort of a side issue, but I tend to prefer a static method of Foo being the factory, rather than have a seperate class called, in this case, FooFactory. So, the base class would implement
  1. class Foo
  2. {
  3. public:
  4. <blah blah blah>
  5.  
  6. static Foo* Factory(); // or use the auto_ptr<> if you are a fancy 'I don't use old C-style stuff' bit hugger :-)
It all depends on what you need.

Your example saves a class (or class hierarchy).
And, it is much simpler than the Factory pattern.
I have used th same thing in quite a few smallish projects.

However it
- doesnt have the flexibility / power of the abstract factory pattern.
- requires that you have complete control of the Foo interface

As to auto_ptr. It isnt a 'I don't use old C-style stuff''.
Using auto_ptr
- allows you to not worry about deleting things (like not having to close a stream obj).
- makes your code more maintainable
- eliminates hard to fix memory leaks when exceptions are thrown.
Quick reply to this message  
Join Date: Jul 2006
Posts: 1
Reputation: klorentzj is an unknown quantity at this point 
Solved Threads: 0
klorentzj klorentzj is offline Offline
Newbie Poster

Re: Factory Design pattern implementation

 
0
  #5
Jul 13th, 2006
Originally Posted by Coding Mage
Hi all,

I have an interesting problem for which I already have a solution, but I have a feeling my solution is less than elegant.

I need to create a Factory class which returns an instance of some child of class Foo. Which child is instantiated depends on the value of some integer parameter. So, for example, the following would work well enough:


  1. class FooFactory
  2. {
  3. public:
  4. Foo* getFooInstance( int id );
  5. }
  6.  
  7. Foo* FooFactory::getFooInstance( int id )
  8. {
  9. switch (id) {
  10. case 1:
  11. return new FooBar();
  12. case 2:
  13. return new FooBoo();
  14. default:
  15. return NULL;
  16. }
  17. }
However, I would need to maintain that switch statement everytime I implement a child class of Foo. So, a better solution, I feel, is to register the child class during static initialization:

  1. // FooFactory.h
  2. class FooFactory
  3. {
  4. typedef Foo* (*FooInstantiator)();
  5. typedef std::map<int, FooInstantiator> InstantiatorMap;
  6.  
  7. public:
  8. Foo* getFooInstance( int id );
  9. static int registerFooInstantiator(int id, FooInstantiator func);
  10.  
  11. private:
  12. static InstantiatorMap m_instantiatorMap;
  13. }
  14.  
  15. // FooFactory.cpp
  16. // For the sake of brevity, let's just assume we've guaranteed that
  17. // m_instantiatorMap already has been constructed.
  18. int FooFactory::registerFooInstantiator(int id, FooInstantiator func)
  19. {
  20. m_instantiatorMap.insert( std::make_pair( id, func ) );
  21. return 1;
  22. }
  23.  
  24. // FooBar.h
  25. class FooBar : public Foo
  26. {
  27. ...
  28. static int isInitialized;
  29. ...
  30. }
  31. Foo* getFooBar();
  32.  
  33. // FooBar.cpp
  34. int FooBar::isInitialized =
  35. FooFactory::registerFooInstantiator( 1, getFooBar );
  36.  
  37. Foo* getFooBar() { return new FooBar(); }
The above solution allows me to create a new Foo child class and add it to the factory without having to modify the factory code.

Can I do better? Having to create a getFooXXX() function for each child seems unnecessary. I was thinking of creating a template function getFoo<T>, declared in FooFactory.h, where T would be the child class. This removes the need for separate getFooXXX functions. Any thoughts?
Here's a thought. You can solve the problem of initializing the map with a static initializer like this:

  1. typedef InstantiatorMap::value_type InstantiatorMapEntryType;
  2. InstantiatorMapEntryType FooFactory::InstantiatorMapEntries[] = {
  3. InstantiatorMapEntryType( 1, &FooBar::GetFooBar ),
  4. InstantiatorMapEntryType( 2, &FooBar::GetFooBoo ),
  5. }
  6. InstantiatorMap FooFactory::m_InstantiatorMap( InstantiatorMapEntries,
  7. InstantiatorMapEntries + sizeof(InstantiatorMapEntries)/sizeof(InstantiatorMapEntries[0]));

This also has the advantage of giving a concise view of which id goes with which function.

You can also make getFooInstance static. Then, you never need to instantiate the FooFactory class.
Quick reply to this message  
Join Date: Apr 2004
Posts: 4,334
Reputation: Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future 
Solved Threads: 234
Team Colleague
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline Offline
long time no c

Re: Factory Design pattern implementation

 
0
  #6
Jul 13th, 2006
Please avoid thread necrophilia.
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
Quick reply to this message  
Closed Thread

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC