By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,602 Members | 1,466 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,602 IT Pros & Developers. It's quick & easy.

Abstract Factory

P: n/a
5 Files
Singleton.h The Singleton

Factory.h The factory creating new objects. The
Base class of the hierachy stores a typelist
identifying the signature of the constructors to
be called in the hierachy by the Factory

StaticFactory Returning refernences to a static object .. typelist
as above.

Phactory An implementation of an Abstract Factory. Each derived class
in a hierachy stores a typelist in itself to identify
the signature
of the constructor it would like the factory to use.
The correct constructor
is called in each derived class by the factory

main.cpp a demonstration of the factories

(Heavy reliance on Boost)
---------------------------------------------------
<main.cpp>
#include<vector>
#include<iostream>
#include"Factory.h"
#include"Phactory.h"

using namespace std;

struct MyClassVoid
{
typedef boost::mpl::list<Constructor_TypeList;
MyClassVoid()
{}
virtual void f()const=0;
virtual ~MyClassVoid()
{}
;
};
struct MyClassVoidDerived :public MyClassVoid
{
MyClassVoidDerived()
{}
virtual void f()const
{
cout << " I am in MyClassVoidDerived \n";
}
virtual ~MyClassVoidDerived()
{}
;
};

namespace
{
Registra<MyClassVoid,MyClassVoidDerived>
theRegistraVoid(std::string("MyClassVoidDerived")) ;
}

struct MyClassDouble
{
typedef boost::mpl::list<doubleConstructor_TypeList;
typedef boost::mpl::list<doublevariant_type_list;
MyClassDouble(double)
{}
virtual void f()
{
cout << " I am in MyClassDouble \n";
}
virtual ~MyClassDouble()
{}
;
};
struct MyClassDoubleDerived :public MyClassDouble
{
typedef boost::mpl::list<doubleconstructor_signature_typel ist;
MyClassDoubleDerived(double x):MyClassDouble(x)
{}
virtual void f()
{
cout << " I am in MyClassDoubleDerived \n";
}
virtual ~MyClassDoubleDerived()
{}
;
};
namespace
{
Registra<MyClassDouble,MyClassDouble>
theRegistra(std::string("MyClassDouble"));
Registra<MyClassDouble,MyClassDoubleDerived>
theRegistraD(std::string("MyClassDoubleDerived"));
}

struct MyClassMultiple
{
typedef
boost::mpl::list<std::string,std::vector<double>,d ouble,MyClassDoubleDerived
Constructor_TypeList;
MyClassMultiple(std::string,std::vector<double>,do uble,MyClassDoubleDerived)
{}
virtual void f()
{
cout << " I am in MyClassMultiple \n";
}
virtual ~MyClassMultiple()
{}
;
};

namespace
{
Registra<MyClassMultiple,MyClassMultiple>
theRegistraM(std::string("MyClassMultiple"));
StaticRegistra<MyClassMultiple,MyClassMultiple>
theStaticRegistraM(std::string("MyClassMultiple"), std::string("String"),
std::vector<double>(2),1.0,MyClassDoubleDerived(1. 0));
}

struct Dummy
{}
;

struct Base
{
typedef boost::mpl::list<double,int,unsigned
long,std::string,std::vector<double>,float,Dummyva riant_type_list;
Base()
{}
virtual void f()const=0;
virtual ~Base()
{}
;
};
struct Derived :public Base
{
typedef boost::mpl::list<double,int,std::string,std::vecto r<double>
constructor_signature_typelist;
Derived(double x_,int n_,const std::string &s_,const
std::vector<double>&v_):
x(x_),n(n_),s(s_),v(v_)
{}
virtual void f()const
{
cout << "My Double is " << x << "\n"
<< "My int is " << n << "\n"
<< "My String is " << s << "\n"
<< "My Vector Size is " << v.size() << "\n";
}
private:
double x;
int n;
std::string s;
std::vector<doublev;
};
namespace
{
const char * theVarNames[]=
{"Double","Int","String","Vector"
};
PhRegistra<Base,Derived>
thePhRegistra(std::string("DerivedObject"),PARAM_N AMES(theVarNames));
}
int main()
{
char ch;

boost::shared_ptr<MyClassVoid>
thePtrVoid(Singleton<Factory<MyClassVoid>
>::instance().RetrieveObject("MyClassVoidDerived") );
thePtrVoid->f();
boost::shared_ptr<MyClassDouble>
thePtrDoubleDerived(Singleton<Factory<MyClassDoubl e>
>::instance().RetrieveObject("MyClassDoubleDerived ",1.0));
thePtrDoubleDerived->f();

boost::shared_ptr<MyClassDouble>
thePtrDouble(Singleton<Factory<MyClassDouble>
>::instance().RetrieveObject("MyClassDouble",1.0)) ;
thePtrDouble->f();

boost::shared_ptr<MyClassMultiple>
thePtrM(Singleton<Factory<MyClassMultiple>
>::instance().RetrieveObject("MyClassMultiple",std ::string("String"),std::vector<double>(2),1.0,MyCl assDoubleDerived(1.0)));
thePtrM->f();

boost::shared_ptr<MyClassMultiple>
thePtrSM(Singleton<StaticFactory<MyClassMultiple>
>::instance().RetrieveObject("MyClassMultiple")) ;
thePtrSM->f();

std::map<std::string,typename boost::make_variant_over<typename
Base::variant_type_list::type>::typetheMap;

theMap["Double"]=1.0;
theMap["Int"]=1;
theMap["String"]="hello";
theMap["Vector"]=std::vector<double>(10);

boost::shared_ptr<Base>
thePtrPhM(Singleton<Phactory<Base>
>::instance().RetrieveObject("DerivedObject",theMa p));
thePtrPhM->f();
cin >>ch;
}

-----------------------------------------------------------------------------------------------

<singleton.h>

#ifndef SINGLETON_HEADER_GUARD
#define SINGLETON_HEADER_GUARD
#include <boost/utility.hpp>

template<class Object>
struct Singleton :boost::noncopyable
{

static Object & instance()
{
static Object theObject;
return theObject;
}
virtual ~Singleton()
{}

}
;

#endif

---------------------------------------------------------------------------

<Factory.h>
#ifndef FACTORY_HEADER_GUARD
#define FACTORY_HEADER_GUARD

#include<string>
#include<map>

#include"Singleton.h"

#include<boost/shared_ptr.hpp>
#include<boost/mpl/size.hpp>
#include<boost/mpl/list.hpp>
#include<boost/mpl/at.hpp>

#include<boost/preprocessor/repetition.hpp>
#include<boost/preprocessor/arithmetic/sub.hpp>

#ifndef MAX_FACTORIES
#define MAX_FACTORIES 10
#endif

// One Registration object per class in a hireachy,
//this is the template blue print for the base classes of
// the registration objects

template
<
class BaseClass,
typename Key = std::string,
unsigned long = boost::mpl::size<typename
BaseClass::Constructor_TypeList>::value
>
struct RegistraBase
{}
;

// This is the template blue print for the concrete classes of
// the registration objects

template
<
class BaseClass,
class Derived,
typename Key = std::string,
unsigned long n = boost::mpl::size<typename
BaseClass::Constructor_TypeList>::value
>
struct Registra :public RegistraBase<BaseClass,Key,n>
{}
;

// This is the factory template blue print of the Factory class

template
<
class BaseClass,
typename Key = std::string ,
unsigned long n = boost::mpl::size<typename
BaseClass::Constructor_TypeList>::value
>
class Factory
{}
;

//Helper Macros
#define PARAM(z,Nb,data) typename boost::mpl::at_c<typename
BaseClass::Constructor_TypeList,Nb>::type P##Nb

#define REGISTRABASE(z,Nb,data)\
template<class BaseClass,typename Key struct
RegistraBase<BaseClass,Key,Nb{ \
virtual boost::shared_ptr<BaseClass>
RetrieveObject(BOOST_PP_ENUM(Nb,PARAM,~))const=0;\
};

BOOST_PP_REPEAT(MAX_FACTORIES,REGISTRABASE,~)
#define FACTORY(z,Nb,data)\
template\
<\
class BaseClass,\
typename Key\
>\
class Factory<BaseClass,Key,Nb{\
public: \
bool Register(const Key & theKey,RegistraBase<BaseClass,Key,Nb>
*theRegistra){ \
return
theInnerMap.insert(InnerMap::value_type(theKey,the Registra)).second; \
}\
\
boost::shared_ptr<BaseClassRetrieveObject(const Key &id
BOOST_PP_COMMA_IF(Nb) BOOST_PP_ENUM(Nb,PARAM,~))const {\
InnerMapIterator theIterator (theInnerMap.find(id));\
if(theIterator==theInnerMap.end())return
boost::shared_ptr<BaseClass>(static_cast<BaseClass *>(0)); \
return theIterator->second->RetrieveObject(
BOOST_PP_ENUM_PARAMS(Nb,P));\
}\
private:\
typedef typename std::map<Key,RegistraBase<BaseClass,Key,Nb*>
InnerMap;\
typedef typename std::map<Key,RegistraBase<BaseClass,Key,Nb>
*>::const_iterator InnerMapIterator;\
std::map<Key,RegistraBase<BaseClass,Key,Nb*theInne rMap;\
};

BOOST_PP_REPEAT(MAX_FACTORIES,FACTORY,~)

// The macro defintions of the Registration Objects

#define REGISTRA(z,Nb,data) \
template<class BaseClass,class Derived,typename Key>\
struct Registra<BaseClass,Derived,Key,Nb>:public
RegistraBase<BaseClass,Key,Nb{\
Registra(const Key & theKey){Singleton<Factory<BaseClass,Key,Nb>
>::instance().Register(theKey,this);}\
boost::shared_ptr<BaseClass>
RetrieveObject(BOOST_PP_ENUM(Nb,PARAM,~))const\
{return boost::shared_ptr<BaseClass>(new Derived(
BOOST_PP_ENUM_PARAMS(Nb,P)));}\
virtual ~Registra(){}\
};

BOOST_PP_REPEAT(MAX_FACTORIES,REGISTRA,~)

#undef MAX_FACTORIES
#undef PARAM
#undef REGISTRA
#undef REGISTRABASE
#undef FACTORY

#include"StaticFactory.h"

#endif

-----------------------------------------------------------------------------------
<StaticFactory.h>
#ifndef STATIC_FACTORY_HEADER_GUARD
#define STATIC_FACTORY_HEADER_GUARD
#include<string>
#include<map>

#include"Singleton.h"

#include<boost/shared_ptr.hpp>
#include<boost/mpl/size.hpp>
#include<boost/mpl/list.hpp>
#include<boost/mpl/at.hpp>

#include<boost/preprocessor/repetition.hpp>
#include<boost/preprocessor/arithmetic/sub.hpp>

#ifndef MAX_STATIC_FACTORIES
#define MAX_STATIC_FACTORIES 10
#endif
template
<
class BaseClass,
typename Key = std::string
>
struct StaticRegistraBase
{
virtual boost::shared_ptr<BaseClassRetrieveObject()const=0 ;
}
;

template
<
class BaseClass,
class Derived,
typename Key = std::string,
unsigned long n = boost::mpl::size<typename
BaseClass::Constructor_TypeList>::value
>
struct StaticRegistra :public StaticRegistraBase<BaseClass,Key>
{}
;

template
<
class BaseClass,
typename Key=std::string
>
class StaticFactory
{
public:
bool Register(const Key & theKey,StaticRegistraBase<BaseClass,Key>
*theRegistra)
{
return
theInnerMap.insert(InnerMap::value_type(theKey,the Registra)).second;
}
boost::shared_ptr<BaseClassRetrieveObject(const Key &id )const
{
InnerMapIterator theIterator (theInnerMap.find(id));
if(theIterator==theInnerMap.end())
return boost::shared_ptr<BaseClass>(static_cast<BaseClass
*>(0));
return theIterator->second->RetrieveObject();
}

private:
typedef typename std::map<Key,StaticRegistraBase<BaseClass,Key*>
InnerMap;
typedef typename std::map<Key,StaticRegistraBase<BaseClass,Key>
*>::const_iterator InnerMapIterator;
std::map<Key,StaticRegistraBase<BaseClass,Key*theI nnerMap;

};

//Helper Macros
#define PARAM(z,Nb,data) typename boost::mpl::at_c<typename
BaseClass::Constructor_TypeList,Nb>::type P##Nb

#define STATICREGISTRA(z,Nb,data) template<class BaseClass,class
Derived,typename Key>\
struct StaticRegistra<BaseClass,Derived,Key, Nb >:public
StaticRegistraBase<BaseClass,Key\
{\
StaticRegistra(const Key & theKey BOOST_PP_COMMA_IF(Nb)
BOOST_PP_ENUM(Nb,PARAM,~)): \
theObjectPtr(new Derived(BOOST_PP_ENUM_PARAMS(Nb,P)))\
{\
Singleton<StaticFactory<BaseClass,Key>
>::instance().Register(theKey,this); \
} \
boost::shared_ptr<BaseClassRetrieveObject()const{r eturn
theObjectPtr;}\
virtual ~StaticRegistra(){} \
private: \
boost::shared_ptr<BaseClasstheObjectPtr; \
};

BOOST_PP_REPEAT(MAX_STATIC_FACTORIES,STATICREGISTR A,~)

#undef MAX_STATIC_FACTORIES
#undef PARAM
#undef STATICREGISTRA

#endif

-------------------------------------------------------------------------------------------------

<Phactory.h>

#ifndef PHACTORY_HEADER_GUARD
#define PHACTORY_HEADER_GUARD
#include<string>
#include<map>
#include<cassert>

#include<boost/shared_ptr.hpp>
#include<boost/variant.hpp>
#include<boost/utility.hpp>
#include<boost/static_assert.hpp>

#include<boost/mpl/size.hpp>
#include<boost/mpl/list.hpp>
#include<boost/mpl/at.hpp>

#include<boost/preprocessor/repetition.hpp>
#ifndef MAX_PHACTORIES
#define MAX_PHACTORIES 10
#endif

template<unsigned long i>
struct unsigned_long
{
enum {value=i};
};

template<class BaseClass>
struct PhRegistraBase
{
typedef typename boost::make_variant_over<typename
BaseClass::variant_type_list::type>::type variant;
typedef std::map<std::string,variantParameterMap;

virtual boost::shared_ptr<BaseClassRetrieveObject(const
std::string &theKey,const ParameterMap& theMap )const=0;
};

template<class BaseClass>
class Phactory
{
public:
typedef typename boost::make_variant_over<typename
BaseClass::variant_type_list::type>::type variant;
typedef std::map<std::string,variantParameterMap;
bool Register(const std::string &theKey, const
PhRegistraBase<BaseClass>* theRegistra)
{
return
theInnerMap.insert(InnerMap::value_type(theKey,the Registra)).second;
}
boost::shared_ptr<BaseClassRetrieveObject(const std::string &id,
const ParameterMap & theMap)const
{
InnerMapIterator theIterator (theInnerMap.find(id));
if(theIterator==theInnerMap.end())
return boost::shared_ptr<BaseClass>(static_cast<BaseClass
*>(0));
return theIterator->second->RetrieveObject(id,theMap);
}
private:
typedef typename std::map<std::string,const
PhRegistraBase<BaseClass*InnerMap;
typedef typename std::map<std::string,const
PhRegistraBase<BaseClass*>::const_iterator InnerMapIterator;
std::map<std::string,const PhRegistraBase<BaseClass*>
theInnerMap;
};
#define PARAM(z,Nb,data) boost::get<const boost::mpl::at_c<signature,
Nb >::type &>(theMap.find(theVarNames[Nb])->second)

#define INNER_RETRIVE_OBJECT(z,Nb,data)\
template<boost::shared_ptr<BaseClassInnerRetrieveO bject< Nb
>(const std::string &theKey,const ParameterMap& theMap)\
const{\
CheckMap(theMap);\
return boost::shared_ptr<BaseClass>(new DerivedClass(
BOOST_PP_ENUM(Nb,PARAM,~) ) \
);\
}

template
<
class BaseClass,
class DerivedClass
>
class PhRegistra:public PhRegistraBase<BaseClass>
{
public:
typedef typename DerivedClass::constructor_signature_typelist
signature;
typedef typename boost::make_variant_over<typename
BaseClass::variant_type_list::type>::type variant;
typedef std::map<std::string,variantParameterMap;

enum {ssize = boost::mpl::size<signature>::value};

template<unsigned long i>
PhRegistra(const std::string &theKey, const char
*theVariableNames[],const unsigned_long<i*p=0)
{
BOOST_STATIC_ASSERT(i==ssize); // Must have ONE variable name
for each paramter of the constructor
for(unsigned long i(0);i<ssize;++i)
theVarNames[i]=std::string(theVariableNames[i]);
Singleton<Phactory<BaseClass>
>::instance().Register(theKey,this);
}

boost::shared_ptr<BaseClassRetrieveObject(const std::string
&theKey,const ParameterMap& theMap)const
{
return InnerRetrieveObject<ssize>(theKey,theMap);
}
template<int i>
boost::shared_ptr<BaseClassInnerRetrieveObject(con st std::string
&theKey,const ParameterMap&)const;

BOOST_PP_REPEAT(MAX_PHACTORIES,INNER_RETRIVE_OBJEC T,~)

private:
void CheckMap(const ParameterMap& theMap)const
{
assert(theMap.size()==ssize);
for(unsigned long i(0);i<ssize;++i)
assert(theMap.find(theVarNames[i])!=theMap.end());
}
std::string theVarNames[ssize];
};

#define PARAM_NAMES(n) n ,
static_cast<unsigned_long<sizeof(n)/sizeof(char*)*>(0)
#undef MAX_PHACTORIES
#undef PARAM
#undef INNER_RETRIVE_OBJECT
#endif

Nov 14 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Nindi wrote:
5 Files
[Snip lengthy code]

What's the C++ language question?

Cheers! --M

Nov 14 '06 #2

P: n/a

Nindi wrote:
<snipped lengthy code>

I stopped counting the syntax errors when i got to 10 (ran out of
fingers).

Nov 14 '06 #3

P: n/a
In article <11**********************@i42g2000cwa.googlegroups .com>,
"mlimber" <ml*****@gmail.comwrote:
Nindi wrote:
5 Files
[Snip lengthy code]

What's the C++ language question?
Yea, I have to admit, I did a search for a question mark and when I
didn't find one, I stopped bothering to read the code. :-/

--
To send me email, put "sheltie" in the subject.
Nov 14 '06 #4

P: n/a
Nindi wrote:
5 Files
Singleton.h The Singleton

Factory.h The factory creating new objects. The
Base class of the hierachy stores a typelist
identifying the signature of the constructors to
be called in the hierachy by the Factory

StaticFactory Returning refernences to a static object .. typelist
as above.

Phactory An implementation of an Abstract Factory. Each derived class
in a hierachy stores a typelist in itself to identify
the signature
of the constructor it would like the factory to use.
The correct constructor
is called in each derived class by the factory

main.cpp a demonstration of the factories

(Heavy reliance on Boost)

This is a link to a post I wrote not too long ago...
http://groups.google.com/group/comp....df450b0?hl=en&

Austria C++ has a generic factory system that also takes constructor
args as well as any key type and works with dynamic libraries.

One of the key issues was ensuring that the singleton was just that.
You need to put your singleton in a .cpp and link it exactly once (not
in any DLL's/.so's) and

Also, learn to use a documentation method. I know my docs suck and I
need to fix that but you need to add some docs...
http://austria.sourceforge.net/dox/h...Factories.html

The unit test for the Austria factory does show how it is used. BTW,
the Austria unit test framework uses the Austria generic abstract factory...

So, what was your question anyway ?

G
Nov 14 '06 #5

P: n/a

Gianni Mariani wrote:
Nindi wrote:
5 Files
Singleton.h The Singleton

Factory.h The factory creating new objects. The
Base class of the hierachy stores a typelist
identifying the signature of the constructors to
be called in the hierachy by the Factory

StaticFactory Returning refernences to a static object .. typelist
as above.

Phactory An implementation of an Abstract Factory. Each derived class
in a hierachy stores a typelist in itself to identify
the signature
of the constructor it would like the factory to use.
The correct constructor
is called in each derived class by the factory

main.cpp a demonstration of the factories

(Heavy reliance on Boost)


This is a link to a post I wrote not too long ago...
http://groups.google.com/group/comp....df450b0?hl=en&

Austria C++ has a generic factory system that also takes constructor
args as well as any key type and works with dynamic libraries.
I will definitley take a look at that. Is it open source ? Are there
any issues with me just using it ?

>
One of the key issues was ensuring that the singleton was just that.
You need to put your singleton in a .cpp and link it exactly once (not
in any DLL's/.so's) and
This is something I am aware of already. I always define my static
instance function in a .cpp.
>
Also, learn to use a documentation method. I know my docs suck and I
need to fix that but you need to add some docs...
http://austria.sourceforge.net/dox/h...Factories.html
Yes I know ... its very bad, I should.
>
The unit test for the Austria factory does show how it is used. BTW,
the Austria unit test framework uses the Austria generic abstract factory...

So, what was your question anyway ?
I just wanted some commenst like you have given just to see if I had
understodd some concepts correctly and implemented correctly. So thanks

Nov 14 '06 #6

P: n/a
Nindi wrote:
Gianni Mariani wrote:
....
I will definitley take a look at that. Is it open source ? Are there
any issues with me just using it ?
It's GPL'd with the gcc exception.
>
>One of the key issues was ensuring that the singleton was just that.
You need to put your singleton in a .cpp and link it exactly once (not
in any DLL's/.so's) and

This is something I am aware of already. I always define my static
instance function in a .cpp.
The Austria factory system goes a little further, it has a single
registry of registries in a single .cpp file in the Austria library.
>
>Also, learn to use a documentation method. I know my docs suck and I
need to fix that but you need to add some docs...
http://austria.sourceforge.net/dox/h...Factories.html

Yes I know ... its very bad, I should.
You'd probably get more comments that way.
>
>The unit test for the Austria factory does show how it is used. BTW,
the Austria unit test framework uses the Austria generic abstract factory...

So, what was your question anyway ?

I just wanted some commenst like you have given just to see if I had
understodd some concepts correctly and implemented correctly. So thanks
K.

Nov 14 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.