2013-09-29 01:08:15 +02:00
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
using std::cout;
|
2013-09-29 01:08:15 +02:00
|
|
|
|
|
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
namespace test {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* === Layer-1: a singleton factory based on a templated static variable === */
|
|
|
|
|
|
|
|
|
|
template<typename I ///< Interface of the product type
|
|
|
|
|
,template <class> class Fac ///< Policy: actual factory to create the instance
|
2013-10-06 17:37:01 +02:00
|
|
|
>
|
2013-09-29 01:08:15 +02:00
|
|
|
struct Holder
|
|
|
|
|
{
|
2013-10-06 18:50:53 +02:00
|
|
|
static I* instance;
|
2013-09-29 01:08:15 +02:00
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
I&
|
2013-09-29 01:08:15 +02:00
|
|
|
get()
|
|
|
|
|
{
|
|
|
|
|
if (!instance)
|
|
|
|
|
{
|
2013-10-06 18:50:53 +02:00
|
|
|
cout << "Singleton Factory: invoke Fabrication ---> instance="<<&instance<<"...\n";
|
|
|
|
|
|
|
|
|
|
instance = Fac<I>::create();
|
2013-09-29 01:08:15 +02:00
|
|
|
}
|
|
|
|
|
return *instance;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
/**
|
|
|
|
|
* allocate storage for the per-type shared
|
|
|
|
|
* (static) variable to hold the singleton instance
|
|
|
|
|
*/
|
|
|
|
|
template<typename I
|
2013-10-06 17:37:01 +02:00
|
|
|
,template <class> class F
|
|
|
|
|
>
|
2013-10-06 18:50:53 +02:00
|
|
|
I* Holder<I,F>::instance;
|
2013-10-06 17:37:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
|
|
|
|
|
template<typename C>
|
2013-10-06 17:37:01 +02:00
|
|
|
struct Factory
|
|
|
|
|
{
|
2013-10-06 18:50:53 +02:00
|
|
|
static C*
|
2013-10-06 17:37:01 +02:00
|
|
|
create()
|
|
|
|
|
{
|
2013-10-06 18:50:53 +02:00
|
|
|
return new C();
|
2013-10-06 17:37:01 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2013-09-29 01:08:15 +02:00
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* === Layer-2: configurable product type === */
|
|
|
|
|
|
|
|
|
|
template<typename I>
|
|
|
|
|
struct Adapter
|
|
|
|
|
{
|
|
|
|
|
typedef I* FactoryFunction (void);
|
|
|
|
|
|
|
|
|
|
static FactoryFunction* factoryFunction;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename C>
|
|
|
|
|
static I*
|
|
|
|
|
concreteFactoryFunction()
|
|
|
|
|
{
|
|
|
|
|
return static_cast<I*> (Factory<C>::create());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename X>
|
|
|
|
|
struct AdaptedConfigurableFactory
|
|
|
|
|
{
|
|
|
|
|
static X*
|
|
|
|
|
create()
|
|
|
|
|
{
|
|
|
|
|
return (*factoryFunction)();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** storage for the per-type shared function pointer to the concrete factory */
|
|
|
|
|
template<typename I>
|
|
|
|
|
typename Adapter<I>::FactoryFunction* Adapter<I>::factoryFunction;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename C>
|
|
|
|
|
struct TypeInfo { };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Singleton factory with the ability to configure the actual product type C
|
|
|
|
|
* only at the \em definition site. Users get to see only the interface type T
|
|
|
|
|
*/
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct ConfigurableHolder
|
|
|
|
|
: Holder<T, Adapter<T>::template AdaptedConfigurableFactory>
|
|
|
|
|
{
|
|
|
|
|
/** define the actual product type */
|
|
|
|
|
template<typename C>
|
|
|
|
|
ConfigurableHolder (TypeInfo<C>)
|
|
|
|
|
{
|
|
|
|
|
Adapter<T>::factoryFunction = &Adapter<T>::template concreteFactoryFunction<C>;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* === Actual usage: Test case fabricating Subject instances === */
|
|
|
|
|
|
2013-09-29 01:08:15 +02:00
|
|
|
struct Subject
|
|
|
|
|
{
|
2013-10-06 18:50:53 +02:00
|
|
|
static int creationCount;
|
2013-09-29 01:08:15 +02:00
|
|
|
|
|
|
|
|
Subject();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2013-10-06 18:50:53 +02:00
|
|
|
typedef ConfigurableHolder<Subject> AccessPoint;
|
2013-09-30 02:09:31 +02:00
|
|
|
|
2013-10-06 17:37:01 +02:00
|
|
|
extern AccessPoint fab;
|
2013-09-30 02:09:31 +02:00
|
|
|
|
2013-09-30 00:58:39 +02:00
|
|
|
|
2013-09-29 01:08:15 +02:00
|
|
|
|
2013-09-30 00:58:39 +02:00
|
|
|
Subject& fabricate();
|
2013-09-29 01:08:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-09-30 00:42:27 +02:00
|
|
|
} // namespace test
|