//////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // The author or Addison-Wesley Longman make no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_ABSTRACTFACTORY_INC_ #define LOKI_ABSTRACTFACTORY_INC_ // $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $ #include "Typelist.h" #include "Sequence.h" #include "TypeManip.h" #include "HierarchyGenerators.h" #include <cassert> /** * \defgroup FactoriesGroup Factories * \defgroup AbstractFactoryGroup Abstract Factory * \ingroup FactoriesGroup * \brief Implements an abstract object factory. */ /** * \class AbstractFactory * \ingroup AbstractFactoryGroup * \brief Implements an abstract object factory. */ namespace Loki { //////////////////////////////////////////////////////////////////////////////// // class template AbstractFactoryUnit // The building block of an Abstract Factory //////////////////////////////////////////////////////////////////////////////// template <class T> class AbstractFactoryUnit { public: virtual T* DoCreate(Type2Type<T>) = 0; virtual ~AbstractFactoryUnit() {} }; //////////////////////////////////////////////////////////////////////////////// // class template AbstractFactory // Defines an Abstract Factory interface starting from a typelist //////////////////////////////////////////////////////////////////////////////// template < class TList, template <class> class Unit = AbstractFactoryUnit > class AbstractFactory : public GenScatterHierarchy<TList, Unit> { public: typedef TList ProductList; template <class T> T* Create() { Unit<T>& unit = *this; return unit.DoCreate(Type2Type<T>()); } }; //////////////////////////////////////////////////////////////////////////////// // class template OpNewFactoryUnit // Creates an object by invoking the new operator //////////////////////////////////////////////////////////////////////////////// template <class ConcreteProduct, class Base> class OpNewFactoryUnit : public Base { typedef typename Base::ProductList BaseProductList; protected: typedef typename BaseProductList::Tail ProductList; public: typedef typename BaseProductList::Head AbstractProduct; ConcreteProduct* DoCreate(Type2Type<AbstractProduct>) { return new ConcreteProduct; } }; //////////////////////////////////////////////////////////////////////////////// // class template PrototypeFactoryUnit // Creates an object by cloning a prototype // There is a difference between the implementation herein and the one described // in the book: GetPrototype and SetPrototype use the helper friend // functions DoGetPrototype and DoSetPrototype. The friend functions avoid // name hiding issues. Plus, GetPrototype takes a reference to pointer // instead of returning the pointer by value. //////////////////////////////////////////////////////////////////////////////// template <class ConcreteProduct, class Base> class PrototypeFactoryUnit : public Base { typedef typename Base::ProductList BaseProductList; protected: typedef typename BaseProductList::Tail ProductList; public: typedef typename BaseProductList::Head AbstractProduct; PrototypeFactoryUnit(AbstractProduct* p = 0) : pPrototype_(p) {} template <class CP, class Base1> friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me, typename Base1::ProductList::Head*& pPrototype); template <class CP, class Base1> friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me, typename Base1::ProductList::Head* pObj); template <class U> void GetPrototype(U*& p) { return DoGetPrototype(*this, p); } template <class U> void SetPrototype(U* pObj) { DoSetPrototype(*this, pObj); } AbstractProduct* DoCreate(Type2Type<AbstractProduct>) { assert(pPrototype_); return pPrototype_->Clone(); } private: AbstractProduct* pPrototype_; }; template <class CP, class Base> inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me, typename Base::ProductList::Head*& pPrototype) { pPrototype = me.pPrototype_; } template <class CP, class Base> inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me, typename Base::ProductList::Head* pObj) { me.pPrototype_ = pObj; } //////////////////////////////////////////////////////////////////////////////// // class template ConcreteFactory // Implements an AbstractFactory interface //////////////////////////////////////////////////////////////////////////////// template < class AbstractFact, template <class, class> class Creator = OpNewFactoryUnit, class TList = typename AbstractFact::ProductList > class ConcreteFactory : public GenLinearHierarchy< typename TL::Reverse<TList>::Result, Creator, AbstractFact> { public: typedef typename AbstractFact::ProductList ProductList; typedef TList ConcreteProductList; }; } // namespace Loki #endif // end file guardian