diff options
Diffstat (limited to 'shared/loki/AbstractFactory.h')
-rw-r--r-- | shared/loki/AbstractFactory.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/shared/loki/AbstractFactory.h b/shared/loki/AbstractFactory.h new file mode 100644 index 00000000..8ff518dc --- /dev/null +++ b/shared/loki/AbstractFactory.h @@ -0,0 +1,185 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 + |