00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015 #ifndef LOKI_ABSTRACTFACTORY_INC_
00016 #define LOKI_ABSTRACTFACTORY_INC_
00017
00018
00019
00020
00021 #include "Typelist.h"
00022 #include "Sequence.h"
00023 #include "TypeManip.h"
00024 #include "HierarchyGenerators.h"
00025
00026 #include <cassert>
00027
00041 namespace Loki
00042 {
00043
00045
00046
00048
00049 template <class T>
00050 class AbstractFactoryUnit
00051 {
00052 public:
00053 virtual T* DoCreate(Type2Type<T>) = 0;
00054 virtual ~AbstractFactoryUnit() {}
00055 };
00056
00058
00059
00061
00062 template
00063 <
00064 class TList,
00065 template <class> class Unit = AbstractFactoryUnit
00066 >
00067 class AbstractFactory : public GenScatterHierarchy<TList, Unit>
00068 {
00069 public:
00070 typedef TList ProductList;
00071
00072 template <class T> T* Create()
00073 {
00074 Unit<T>& unit = *this;
00075 return unit.DoCreate(Type2Type<T>());
00076 }
00077 };
00078
00080
00081
00083
00084 template <class ConcreteProduct, class Base>
00085 class OpNewFactoryUnit : public Base
00086 {
00087 typedef typename Base::ProductList BaseProductList;
00088
00089 protected:
00090 typedef typename BaseProductList::Tail ProductList;
00091
00092 public:
00093 typedef typename BaseProductList::Head AbstractProduct;
00094 ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
00095 {
00096 return new ConcreteProduct;
00097 }
00098 };
00099
00101
00102
00103
00104
00105
00106
00107
00109
00110 template <class ConcreteProduct, class Base>
00111 class PrototypeFactoryUnit : public Base
00112 {
00113 typedef typename Base::ProductList BaseProductList;
00114
00115 protected:
00116 typedef typename BaseProductList::Tail ProductList;
00117
00118 public:
00119 typedef typename BaseProductList::Head AbstractProduct;
00120
00121 PrototypeFactoryUnit(AbstractProduct* p = 0)
00122 : pPrototype_(p)
00123 {}
00124
00125 template <class CP, class Base1>
00126 friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me,
00127 typename Base1::ProductList::Head*& pPrototype);
00128
00129 template <class CP, class Base1>
00130 friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me,
00131 typename Base1::ProductList::Head* pObj);
00132
00133 template <class U>
00134 void GetPrototype(U*& p)
00135 { return DoGetPrototype(*this, p); }
00136
00137 template <class U>
00138 void SetPrototype(U* pObj)
00139 { DoSetPrototype(*this, pObj); }
00140
00141 AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
00142 {
00143 assert(pPrototype_);
00144 return pPrototype_->Clone();
00145 }
00146
00147 private:
00148 AbstractProduct* pPrototype_;
00149 };
00150
00151 template <class CP, class Base>
00152 inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me,
00153 typename Base::ProductList::Head*& pPrototype)
00154 { pPrototype = me.pPrototype_; }
00155
00156 template <class CP, class Base>
00157 inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me,
00158 typename Base::ProductList::Head* pObj)
00159 { me.pPrototype_ = pObj; }
00160
00162
00163
00165
00166 template
00167 <
00168 class AbstractFact,
00169 template <class, class> class Creator = OpNewFactoryUnit,
00170 class TList = typename AbstractFact::ProductList
00171 >
00172 class ConcreteFactory
00173 : public GenLinearHierarchy<
00174 typename TL::Reverse<TList>::Result, Creator, AbstractFact>
00175 {
00176 public:
00177 typedef typename AbstractFact::ProductList ProductList;
00178 typedef TList ConcreteProductList;
00179 };
00180
00181 }
00182
00183
00184 #endif // end file guardian
00185