TITLE: example designs using factory patterns [ The term factory pattern comes from "Design Patterns: Elements of Reusable O-O Software", by Gamma, et al. It is a way to partition classes to decouple the client of an object instance from the particulars of its exact type and its creation requirements. -adc ] DD: Dharmesh Dadbhawala [...] I am trying to use the Factory pattern. What I am supposed to do us to Initialize an object base of different kind of objects. For example I have objects of TYpe A, B and each of them have speacialized types A1...An and B1....Bn which differ in the following ways 1. semantically 2. information content i.e Init data is veru different 3. They are stored in different containers. 4. Some are static in nature and never get deleted and some are dynamic in nature thus special operations need to be done while creating them like allocating a unique Object Id ( integer) , manage recycling of Id's etc.... Thus our design team thought of the following design two designs DESIGN A: class AbstractFactoryForA { virtual make(); } class concreteFactorA1 : public class AbstractFactoryForA { create and store A1 } class concreteFactorA2 : public class AbstractFactoryForA { create and store A } The same goes for objecs of type B ..... What I then have is a Map container which uses the specialized types of A ie. A1, A2, A3 as keys and return me the Factors for that type so I have mapforA < objectype , Factor* >; mapforB < objectype , Fcator* >; This map acts as an information repository for the finding the correct factor objects. DESIGN 2: [...] class AbstractFactoryForA { virtual make(); } template< class Type > class FactorForA : public pripFactory { // ---------------------------------------------- template FactorA ObjId *make( id, char *initData ) { // --------------------------------------------- make objects of type A }; }; Then I store insantiations of this template class in the map which is the same as shown above.and do the same for objects of type B. Questions: 1. Is it really any big difference in both designs i.e. separate concrete instantiations or template approach ? 2. Should I have separate factories for different types as we do in the real world? [...] RESPONSE: Steve Hickman , 10 May 96 I think what you are trying to get at involves a combination of Singleton and AbstractFactory. Here's the way I implement it: typedef AbstractFactory * pAbstractFactory; typedef map > FactoryMap; class AbstractFactory { protected: static FactoryMap factories; public: static find(FactoryType key); }; class ConcreteFactory1: public AbstractFactory { protected: ConcreteFactory1(); static AbstractFactory *inst; public: static AbstractFactory *instance(); static FactoryType key(); }; class ConcreteFactory2: public AbstractFactory { protected: ConcreteFactory2(); static AbstractFactory* inst; public: static AbstractFactory *instance(); static FactoryType key(); }; AbstractFactory * ConcreteFactory1::instance() { if (!inst) { inst = new ConcreteFactory1(); factories.insert(key(),inst); } } AbstractFactory * ConcreteFactory2::instance() { if (!inst) { inst = new ConcreteFactory1(); factories.insert(key(),inst); } } AbstractFactory * AbstractFactory::find(FactoryType key) { FactoryMap::iterator iter = factories.find(key); if (iter == factories.end()) return NULL; else return (*iter).second; } ------ end of code ---- The above setup insures that I only get one of each concrete factory (using Singleton) and also insures that I can find the instance when I need it. Obviously, this setup requires the creation of the concrete factories in some startup code, but it does provide the flexibility of programming to the AbstractFactory API throughout your code. RESPONSE: "Robert C. Martin" , 10 May 96 [...] There is nothing wrong with the template approach as long as all the created objects are created with the same procedure. However, you indicated above that some of the created objects will require different construction arguments. While it is not impossible to accomplish this with templates, it does increase the difficulty level somewhat. To do it, you use explicit template definitions as below. template class AFactory { public: A* Make() {return new T;} }; // Explicit for A2 which needs an integer construction argument. A* A2::Make() {return new A2(1);} ------------------------- The notion of a Map of factories is very useful. It allows you to create objects whose actual types vary with some kind of parameter, and yet prevents the modules requesting that creation from depending upon those actual types. This prevents a lot of headaches and recompiles later on.