AbstractFactory.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Wesley Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_ABSTRACTFACTORY_INC_
00016 #define LOKI_ABSTRACTFACTORY_INC_
00017 
00018 // $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $
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 // class template AbstractFactoryUnit
00046 // The building block of an Abstract Factory
00048 
00049     template <class T>
00050     class AbstractFactoryUnit
00051     {
00052     public:
00053         virtual T* DoCreate(Type2Type<T>) = 0;
00054         virtual ~AbstractFactoryUnit() {}
00055     };
00056 
00058 // class template AbstractFactory
00059 // Defines an Abstract Factory interface starting from a typelist
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 // class template OpNewFactoryUnit
00081 // Creates an object by invoking the new operator
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 // class template PrototypeFactoryUnit
00102 // Creates an object by cloning a prototype
00103 // There is a difference between the implementation herein and the one described
00104 //     in the book: GetPrototype and SetPrototype use the helper friend 
00105 //     functions DoGetPrototype and DoSetPrototype. The friend functions avoid
00106 //     name hiding issues. Plus, GetPrototype takes a reference to pointer
00107 //     instead of returning the pointer by value.
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 // class template ConcreteFactory
00163 // Implements an AbstractFactory interface
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 } // namespace Loki
00182 
00183 
00184 #endif // end file guardian
00185 

Generated on Sun Feb 25 16:52:20 2007 for Loki by  doxygen 1.5.1-p1