Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Factories.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_Factories_h_
00003 #define INCLUDED_Factories_h_
00004 
00005 //! A factory interface which doesn't actually allow anything to be produced (for completeness, like 'NULL')
00006 template<typename=void>
00007 struct FactoryInvalidT {
00008   //! concrete class for not doing anything
00009   template<class U> struct Factory : public FactoryInvalidT<U> {};
00010 };
00011 //! specialization: all invalid factories are the same...
00012 typedef FactoryInvalidT<> FactoryInvalid;
00013 
00014 // Alternate implementation of FactoryInvalid just for reference:
00015 // (I prefer the one used above though, because it provides a (unused) template for the base class like the other factory types)
00016 #if 0
00017 //! A factory interface which doesn't actually allow anything to be produced (for completeness, like 'NULL')
00018 struct FactoryInvalid {
00019   //! concrete class for not doing anything (prototype here, "implementation" follows)
00020   template<class U> struct Factory;
00021 };
00022 //! implementation of concrete class for not doing anything
00023 template<class U> struct FactoryInvalid::Factory : public FactoryInvalid {};
00024 #endif
00025 
00026 
00027 //! Untyped base class for factories which don't require any arguments to construct their product, see Factories.h file notes (see Factory0Arg)
00028 /*! Note that this does not mean the product has to be constructed without arguments... see Factory0Arg1Static for example. */
00029 struct Factory0ArgBase {
00030   //! functor interface for constructing the product
00031   virtual void* construct()=0; 
00032   //! explicit destructor to avoid warnings regarding virtual functions without virtual destructor
00033   virtual ~Factory0ArgBase() {}
00034 };
00035 //! Typed base class for factories which don't require any arguments to construct their product, see Factories.h file notes
00036 /*! Note that this does not mean the product has to be constructed without arguments... see Factory0Arg1Static for example. */
00037 template<class Base>
00038 struct Factory0Arg : public Factory0ArgBase {
00039   //! functor interface for constructing the product
00040   virtual Base* operator()()=0; 
00041   virtual void* construct() { return operator()(); }
00042   //! concrete class for constructing products of a specified subtype of Base
00043   template<class T> struct Factory : public Factory0Arg<Base> {
00044     virtual Base* operator()() { return new T; } //!< functor for constructing the product
00045   };
00046 };
00047 //! This class produces objects based on a constant specified as a template parameter
00048 /*! You could also implement this by adding a member field to the factory and passing that to
00049  *  the target constuctor instead of the non-type template parameter (which has some restrictions).
00050  *  See Factory0Arg1Member */
00051 template<class Base, class S1, S1 s1>
00052 struct Factory0Arg1Static : public Factory0Arg<Base> {
00053   //! concrete class for constructing products of a specified subtype of Base
00054   template<class T> struct Factory : public Factory0Arg1Static<Base,S1,s1> {
00055     virtual Base* operator()() { return new T(s1); } //!< functor for constructing the product
00056   };
00057 };
00058 //! This class produces objects based on a constant specified as a factory member
00059 /*! You could also implement this by using a non-type template parameter argument, see Factory0Arg1Static. */
00060 template<class Base, class M1>
00061 struct Factory0Arg1Member : public Factory0Arg<Base> {
00062   //! concrete class for constructing products of a specified subtype of Base
00063   template<class T> struct Factory : public Factory0Arg1Member<Base,M1> {
00064     Factory() : m1() {} //!< use default constructor for #m1
00065     explicit Factory(const M1& im1) : m1(im1) {} //!< use specified value to initalize #m1
00066     M1 m1; //!< storage for the product's constructor value
00067     virtual Base* operator()() { return new T(m1); } //!< functor for constructing the product
00068   };
00069 };
00070 //! This class produces objects based on constant values specified as a template parameters
00071 /*! You could also implement this by adding member fields to the factory and passing that to
00072  *  the target constuctor instead of the non-type template parameter (which has some restrictions).
00073  *  See Factory0Arg1Member for an example how this is done. */
00074 template<class Base, class S1, S1 s1, class S2, S2 s2>
00075 struct Factory0Arg2Static : public Factory0Arg<Base> {
00076   //! concrete class for constructing products of a specified subtype of Base
00077   template<class T> struct Factory : public Factory0Arg2Static<Base,S1,s1,S2,s2> {
00078     virtual Base* operator()() { return new T(s1,s2); } //!< functor for constructing the product
00079   };
00080 };
00081 //! A factory for singleton classes which return the instance via getInstance()
00082 template<class T>
00083 class SingletonFactory : public Factory0Arg<T> {
00084 public:
00085   //! returns the singleton instance, factory-style
00086   virtual T* operator()() { return &T::getInstance(); }
00087 };
00088 
00089 
00090 
00091 //! Untyped base class for factories which require a single argument to construct their product, which is passed to the concrete Factory's functor (see Factory1Arg)
00092 /*! Note that this does not mean the product can only be constructed with only one argument... see Factory1Arg1Static for example. */
00093 template<class A1>
00094 struct Factory1ArgBase {
00095   //! functor interface for constructing the product
00096   virtual void* construct(const A1& a1)=0; 
00097   //! explicit destructor to avoid warnings regarding virtual functions without virtual destructor
00098   virtual ~Factory1ArgBase() {}
00099 };
00100 //! Typed base class for factories which require a single argument to construct their product, which is passed to the concrete Factory's functor
00101 /*! Note that this does not mean the product can only be constructed with only one argument... see Factory1Arg1Static for example. */
00102 template<class Base, class A1>
00103 struct Factory1Arg : public Factory1ArgBase<A1> {
00104   //! functor interface for constructing the product
00105   virtual Base* operator()(const A1& a1)=0;
00106   virtual void* construct(const A1& a1) { return operator()(a1); }
00107   //! concrete class for constructing products of a specified subtype of Base
00108   template<class T> struct Factory : public Factory1Arg<Base,A1> {
00109     virtual Base* operator()(const A1& a1) { return new T(a1); } //!< functor for constructing the product
00110   };
00111 };
00112 //! This class produces objects based on a functor argument and a constant specified as a template parameter
00113 /*! You could also implement this by adding a member field to the factory and passing that to
00114  *  the target constuctor instead of the non-type template parameter (which has some restrictions).
00115  *  See Factory0Arg1Member for an example how this is done. */
00116 template<class Base, class A1, class S1, S1 s1>
00117 struct Factory1Arg1Static : public Factory1Arg<Base,A1> {
00118   //! concrete class for constructing products of a specified subtype of Base
00119   template<class T> struct Factory : public Factory1Arg1Static<Base,A1,S1,s1> {
00120     virtual Base* operator()(const A1& a1) { return new T(a1,s1); } //!< functor for constructing the product
00121   };
00122 };
00123 //! This class produces objects based on a constant specified as a template parameter and a constructor argument
00124 /*! You could also implement this by adding a member field to the factory and passing that to
00125  *  the target constuctor instead of the non-type template parameter (which has some restrictions).
00126  *  See Factory0Arg1Member for an example how this is done. */
00127 template<class Base, class S1, S1 s1, class A1>
00128 struct Factory1Static1Arg : public Factory1Arg<Base,A1> {
00129   //! concrete class for constructing products of a specified subtype of Base
00130   template<class T> struct Factory : public Factory1Static1Arg<Base,S1,s1,A1> {
00131     virtual Base* operator()(const A1& a1) { return new T(s1,a1); } //!< functor for constructing the product
00132   };
00133 };
00134 
00135 
00136 
00137 //! Base class for factories which can create products more than one way, in this case via default constructor (0 arguments) or 1-argument constructor
00138 /*! We use multiple inheritance to combine the Factory0Arg and Factory1Arg base classes.  Keep in mind however,
00139  *  that all product subtypes must support all constr*/
00140 template<class Base, class A1>
00141 struct Factory0_1Arg : public virtual Factory0Arg<Base>, public virtual Factory1Arg<Base,A1> {
00142   using Factory0Arg<Base>::operator();
00143   using Factory1Arg<Base,A1>::operator();
00144   //! concrete class for constructing products of a specified subtype of Base
00145   template<class T> struct Factory : public Factory0_1Arg<Base,A1> {
00146     virtual Base* operator()() { return new T; } //!< 0 argument functor for constructing the product
00147     virtual Base* operator()(const A1& a1) { return new T(a1); } //!< 1 argument functor for constructing the product
00148   };
00149 };
00150 //! Variant of Factory0_1Arg, this uses a constant non-type template parameter to specify a default value to use when the 0-argument functor is called...
00151 /*! Thus, we only ever call the product's 1 argument constructor, but provide more options in the factory interface... */
00152 template<class Base, class S1, S1 s1, class A1>
00153 struct Factory1Static_1Arg : public Factory0_1Arg<Base,A1> {
00154   //! concrete class for constructing products of a specified subtype of Base
00155   template<class T> struct Factory : public Factory1Static_1Arg<Base,S1,s1,A1> {
00156     virtual Base* operator()() { return new T(s1); } //!< 0 argument functor for constructing the product using the static value
00157     virtual Base* operator()(const A1& a1) { return new T(a1); } //!< 1 argument functor for constructing the product
00158   };
00159 };
00160 
00161 /*! @file
00162  * @brief Defines a variety of factory templates which can be used with FamilyFactory.
00163  * This is not (and couldn't be) an exhaustive list of Factory configurations.  It provides some commonly used
00164  * configurations, and should give you some examples and ideas how to create your own for more complex cases.
00165  *
00166  * Factory0Arg and Factory1Arg allow you to instantiate classes with 0 or 1 arguments respectively.  Subclasses of
00167  * these interfaces allow you to specify additional parameters to the product's constructor call.  Factory0_1Arg
00168  * shows how to combine Factory configurations so you can have multiple constructor options at runtime.
00169  *
00170  * @author ejt (Creator)
00171  */
00172 
00173 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:38 2016 by Doxygen 1.6.3