Abstract Factory

Discussion in 'C++' started by Nindi, Nov 14, 2006.

  1. Nindi

    Nindi Guest

    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<double> Constructor_TypeList;
    typedef boost::mpl::list<double> variant_type_list;
    MyClassDouble(double)
    {}
    virtual void f()
    {
    cout << " I am in MyClassDouble \n";
    }
    virtual ~MyClassDouble()
    {}
    ;
    };
    struct MyClassDoubleDerived :public MyClassDouble
    {
    typedef boost::mpl::list<double> constructor_signature_typelist;
    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>,double,MyClassDoubleDerived
    > Constructor_TypeList;


    MyClassMultiple(std::string,std::vector<double>,double,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,Dummy> variant_type_list;
    Base()
    {}
    virtual void f()const=0;
    virtual ~Base()
    {}
    ;
    };
    struct Derived :public Base
    {
    typedef boost::mpl::list<double,int,std::string,std::vector<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<double> v;
    };
    namespace
    {
    const char * theVarNames[]=
    {"Double","Int","String","Vector"
    };
    PhRegistra<Base,Derived>
    thePhRegistra(std::string("DerivedObject"),PARAM_NAMES(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<MyClassDouble>
    >::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,MyClassDoubleDerived(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>::type> theMap;

    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",theMap));

    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,theRegistra)).second; \
    }\
    \
    boost::shared_ptr<BaseClass> RetrieveObject(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> *> theInnerMap;\
    };

    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<BaseClass> RetrieveObject()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,theRegistra)).second;
    }
    boost::shared_ptr<BaseClass> RetrieveObject(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> *> theInnerMap;

    };

    //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<BaseClass> RetrieveObject()const{return
    theObjectPtr;}\
    virtual ~StaticRegistra(){} \
    private: \
    boost::shared_ptr<BaseClass> theObjectPtr; \
    };

    BOOST_PP_REPEAT(MAX_STATIC_FACTORIES,STATICREGISTRA,~)

    #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,variant> ParameterMap;

    virtual boost::shared_ptr<BaseClass> RetrieveObject(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,variant> ParameterMap;
    bool Register(const std::string &theKey, const
    PhRegistraBase<BaseClass>* theRegistra)
    {
    return
    theInnerMap.insert(InnerMap::value_type(theKey,theRegistra)).second;
    }
    boost::shared_ptr<BaseClass> RetrieveObject(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<BaseClass> InnerRetrieveObject< 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,variant> ParameterMap;

    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=std::string(theVariableNames);
    Singleton<Phactory<BaseClass>
    >::instance().Register(theKey,this);

    }

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

    BOOST_PP_REPEAT(MAX_PHACTORIES,INNER_RETRIVE_OBJECT,~)

    private:
    void CheckMap(const ParameterMap& theMap)const
    {
    assert(theMap.size()==ssize);
    for(unsigned long i(0);i<ssize;++i)
    assert(theMap.find(theVarNames)!=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
     
    Nindi, Nov 14, 2006
    #1
    1. Advertising

  2. Nindi

    mlimber Guest

    Nindi wrote:
    > 5 Files

    [Snip lengthy code]

    What's the C++ language question?

    Cheers! --M
     
    mlimber, Nov 14, 2006
    #2
    1. Advertising

  3. Nindi

    Salt_Peter Guest

    Nindi wrote:
    <snipped lengthy code>

    I stopped counting the syntax errors when i got to 10 (ran out of
    fingers).
     
    Salt_Peter, Nov 14, 2006
    #3
  4. Nindi

    Daniel T. Guest

    In article <>,
    "mlimber" <> wrote:

    > 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.
     
    Daniel T., Nov 14, 2006
    #4
  5. 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.lang.c /msg/225c720a0df450b0?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/html/group__GenericFactories.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
     
    Gianni Mariani, Nov 14, 2006
    #5
  6. Nindi

    Nindi Guest

    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.lang.c /msg/225c720a0df450b0?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/html/group__GenericFactories.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
     
    Nindi, Nov 14, 2006
    #6
  7. 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/html/group__GenericFactories.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.
     
    Gianni Mariani, Nov 14, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christer
    Replies:
    3
    Views:
    960
    Drebin
    Aug 27, 2003
  2. =?Utf-8?B?bWF4?=

    Design Pattern - Abstract Factory

    =?Utf-8?B?bWF4?=, Oct 18, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    655
    tdavisjr
    Oct 18, 2005
  3. Medi Montaseri
    Replies:
    17
    Views:
    879
    Medi Montaseri
    Sep 3, 2003
  4. Sebastian Faust

    Generic Abstract Factory

    Sebastian Faust, Oct 27, 2003, in forum: C++
    Replies:
    3
    Views:
    718
    Gianni Mariani
    Oct 27, 2003
  5. C#
    Replies:
    4
    Views:
    412
Loading...

Share This Page