1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 // purpose is hereby granted without fee, provided that the above copyright
9 // notice appear in all copies and that both that copyright notice and this
10 // permission notice appear in supporting documentation.
11 // The author or Addison-Wesley Longman make no representations about the
12 // suitability of this software for any purpose. It is provided "as is"
13 // without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_ABSTRACTFACTORY_INC_
16 #define LOKI_ABSTRACTFACTORY_INC_
18 // $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $
23 #include "TypeManip.h"
24 #include "HierarchyGenerators.h"
29 * \defgroup FactoriesGroup Factories
30 * \defgroup AbstractFactoryGroup Abstract Factory
31 * \ingroup FactoriesGroup
32 * \brief Implements an abstract object factory.
36 * \class AbstractFactory
37 * \ingroup AbstractFactoryGroup
38 * \brief Implements an abstract object factory.
44 ////////////////////////////////////////////////////////////////////////////////
45 // class template AbstractFactoryUnit
46 // The building block of an Abstract Factory
47 ////////////////////////////////////////////////////////////////////////////////
50 class AbstractFactoryUnit
53 virtual T *DoCreate(Type2Type<T>) = 0;
54 virtual ~AbstractFactoryUnit() {}
57 ////////////////////////////////////////////////////////////////////////////////
58 // class template AbstractFactory
59 // Defines an Abstract Factory interface starting from a typelist
60 ////////////////////////////////////////////////////////////////////////////////
65 template <class> class Unit = AbstractFactoryUnit
67 class AbstractFactory : public GenScatterHierarchy<TList, Unit>
70 typedef TList ProductList;
72 template <class T> T *Create()
74 Unit<T>& unit = *this;
75 return unit.DoCreate(Type2Type<T>());
79 ////////////////////////////////////////////////////////////////////////////////
80 // class template OpNewFactoryUnit
81 // Creates an object by invoking the new operator
82 ////////////////////////////////////////////////////////////////////////////////
84 template <class ConcreteProduct, class Base>
85 class OpNewFactoryUnit : public Base
87 typedef typename Base::ProductList BaseProductList;
90 typedef typename BaseProductList::Tail ProductList;
93 typedef typename BaseProductList::Head AbstractProduct;
94 ConcreteProduct *DoCreate(Type2Type<AbstractProduct>)
96 return new ConcreteProduct;
100 ////////////////////////////////////////////////////////////////////////////////
101 // class template PrototypeFactoryUnit
102 // Creates an object by cloning a prototype
103 // There is a difference between the implementation herein and the one described
104 // in the book: GetPrototype and SetPrototype use the helper friend
105 // functions DoGetPrototype and DoSetPrototype. The friend functions avoid
106 // name hiding issues. Plus, GetPrototype takes a reference to pointer
107 // instead of returning the pointer by value.
108 ////////////////////////////////////////////////////////////////////////////////
110 template <class ConcreteProduct, class Base>
111 class PrototypeFactoryUnit : public Base
113 typedef typename Base::ProductList BaseProductList;
116 typedef typename BaseProductList::Tail ProductList;
119 typedef typename BaseProductList::Head AbstractProduct;
121 PrototypeFactoryUnit(AbstractProduct *p = 0)
125 template <class CP, class Base1>
126 friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me,
127 typename Base1::ProductList::Head*& pPrototype);
129 template <class CP, class Base1>
130 friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me,
131 typename Base1::ProductList::Head *pObj);
134 void GetPrototype(U*& p)
136 return DoGetPrototype(*this, p);
140 void SetPrototype(U *pObj)
142 DoSetPrototype(*this, pObj);
145 AbstractProduct *DoCreate(Type2Type<AbstractProduct>)
148 return pPrototype_->Clone();
152 AbstractProduct *pPrototype_;
155 template <class CP, class Base>
156 inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me,
157 typename Base::ProductList::Head*& pPrototype)
159 pPrototype = me.pPrototype_;
162 template <class CP, class Base>
163 inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me,
164 typename Base::ProductList::Head *pObj)
166 me.pPrototype_ = pObj;
169 ////////////////////////////////////////////////////////////////////////////////
170 // class template ConcreteFactory
171 // Implements an AbstractFactory interface
172 ////////////////////////////////////////////////////////////////////////////////
177 template <class, class> class Creator = OpNewFactoryUnit,
178 class TList = typename AbstractFact::ProductList
180 class ConcreteFactory
181 : public GenLinearHierarchy<
182 typename TL::Reverse<TList>::Result, Creator, AbstractFact>
185 typedef typename AbstractFact::ProductList ProductList;
186 typedef TList ConcreteProductList;
192 #endif // end file guardian