编程模式之工厂——我这样写工厂

本文介绍了如何使用泛型工厂模式和注册代理来简化对象创建,通过模板类和宏定义,实现工厂类的动态注册和对象的动态创建。这种方法允许程序员在不修改工厂代码的情况下,只需在具体类的cpp文件末尾注册即可。此外,文章还展示了如何通过宏定义创建对象,使得代码更加简洁。这种设计模式在需要动态创建不同类型的对象,特别是当对象的类型在不同模块之间分布时,非常有用。
摘要由CSDN通过智能技术生成

工厂模式用来封装具体对象的创建,但我们没写一个具体的需要创建的对象类,是否要修改工厂呢?或者需要在某个地方进行注册。这样,每写一个具体的对象类,还需要在另外一个地方编写注册代码,程序员都是懒人,能省事儿,绝不费事儿。看代码:

#pragma once

#include "T_KeyPVector.h"

using namespace std;

/**

*ICreator 是创建器接口,它创建RootClass类型的对象,具体类型可以是RootClass类的子类

*/

template<class RootClass>

class ICreator

{

public:

    virtual RootClass* Create() = 0;

};

/**

*Creator 是ICreator的实现

*ConcreateClass是RootClass的子类,Creator创建ConcreateClass,

*以RootClass的形式返回创建的对象

*/

template<class ConcreteClass,class RootClass>

class Creator : public ICreator<RootClass>

{

public:

    virtual RootClass* Create()

    {

        return new ConcreteClass();

    }

};

/**

*工厂负责具体创建对象,工厂注册了各种RootClass子类的创建器

*并使用这些创建器根据Key值来创建具体对象。

*工厂是用户主要使用的类,此工厂具体使用的时候需要具体实现为一个Singleton的

*具体的Singleton的工厂加以应用

*/

template <class RootClass,class KeyType>

class Factory

{

public:

    typedef ICreator<RootClass> CCreator;

    typedef T_KeyVector<KeyType,CCreator*> CreatorMap;

public:

    class Iterator

    {

    public:

        Iterator(CreatorMap* pMap)

            :m_pMap(pMap),m_it(pMap->begin())

        {

        }

        Iterator(CreatorMap* pMap,int index)

            :m_it(pMap->get(index))

        {

        }

        Iterator(const Iterator& it)

            :m_pMap(it.m_pMap)

            ,m_it(it.m_it){}

       

        Iterator& operator = (const Iterator& it)

        {

            if(this == &it)

                return *this;

            m_pMap = it.m_pMap;

            m_it = it.m_it;

            return *this;

        }

        ~Iterator(){}

    public:

        bool valid()

        {

            return m_it.valid();

        }

        void next()

        {

            m_it.next();

        }

        RootClass* Create()

        {

            return (*m_it)->Create();

        }

        KeyType key()

        {

            return m_it.key();

        }

    private:

        CreatorMap* m_pMap;

        typename CreatorMap::Iterator m_it;

    };

private:

    typedef pair<KeyType,CCreator*> MapPair;

public:

    RootClass* Create(KeyType key)

    {

        CreatorMap::Iterator it = m_mapCreators.find(key);

        if(it.valid())

        {

            return (*it)->Create();

        }

        return NULL;

    }

    void Registe(KeyType key,CCreator* pCreator)

    {

        m_mapCreators.push_back(key,pCreator);

    }

    void Deregiste(KeyType key)

    {

        m_mapCreators.erase(key);

    }

    Iterator begin()

    {

        return Iterator(&m_mapCreators);

    }

    virtual ~Factory()

    {

        m_mapCreators.clear();

    };

    int size()

    {

        return (int)m_mapCreators.size();

    }

    Iterator get(int index)

    {

        return Iterator(&m_mapCreators,index);

    }

protected:

    Factory(){};

private:

    CreatorMap m_mapCreators;

};

/**

*注册代理器,用户使用这个类在Factory中注册Creator,注册过程为在.cpp中声明静态注册代理类变量即可

*ConcreateClass:Factory中要生成的类

*RootClass:Factory中执行生成动作后返回的类型(RootClass是ConcreateClass的父类)

*KeyType:使用那种类型来标识生要生成的对象类型。

*SingletonFactory:Factory的子类,要求其是一个单间模式的类,是真正的工厂

*/

template<class ConcreteClass,class RootClass,class KeyType,class SingletonFactory>

class RegisteProxy

{

public:

    typedef Creator<ConcreteClass,RootClass> CCreator;

public:

    RegisteProxy(KeyType key)

    {

        m_key = key;

        SingletonFactory::Instance().Registe(key,&m_creator);

    }

    ~RegisteProxy()

    {

        SingletonFactory::Instance().Deregiste(m_key);

    }

private:

    CCreator m_creator;

    KeyType m_key;

};

/**

*使用宏来简化注册过程,用户在编写一个IClassname的具体实现类的时候,可以在其.cpp最后使用这个宏来注册

*/

#define REGISTE_CREATOR(SingletonFactory, ConcreateClassname,IClassname,KeyTypename,key) \

    static RegisteProxy<ConcreateClassname,IClassname,KeyTypename,SingletonFactory> \

    g_proxy_##ConcreateClassname(key);

/**

*声明单件的Factory,并将此类作为导出类

*当用户在Dll中使用工厂的时候,一般使用此宏来声明SingletonFactory

*/

#define DECLEAR_SINGLETON_FACTORY_EXT(SingletonFactory, IClassname, KeyTypename) \

class AFX_EXT_CLASS SingletonFactory : public Factory<IClassname,KeyTypename> \

{ \

protected: \

     SingletonFactory(){}; \

public: \

    static SingletonFactory& Instance(); \

};

/**

*声明单件Factory

*/

#define DECLEAR_SINGLETON_FACTORY(SingletonFactory, IClassname, KeyTypename) \

class SingletonFactory : public Factory<IClassname,KeyTypename> \

{ \

protected: \

    SingletonFactory(){}; \

public: \

    static SingletonFactory& Instance(); \

};

/**

*单件的Factory的实现代码

*/

#define IMPLEMENT_SINGLETON_FACTORY(SingletonFactory) \

SingletonFactory& SingletonFactory::Instance() \

{ \

    static SingletonFactory f; \

    return f; \

}

注册代理和几个宏,可以让我们大大减少工厂应用的代价,而且,这段工厂代码是通用代码,只要几行配置,就能得到一个工厂,并且可以方便的注册。下面是应用实例:

class IObj

{

public:

virtual ~IObj();

}

下面我要创建一个创建以IObj为基类的对象的工厂:

#pragma  once

#include "Factory.h"

class IGEObj;

DECLEAR_SINGLETON_FACTORY(Obj_Factory,IObj,CString)

#define REGISTE_OBJ(classname) \

    REGISTE_CREATOR(Obj_Factory,classname,IObj,CString,#classname)

#define Create_Obj(classname)\

    dynamic_cast<classname*>(Obj_Factory::Instance().Create(#classname))

#define Create_Obj_2(key) \

    Obj_Factory::Instance().Create(key)

以上是头文件代码,下面是cpp文件代码:只有一行

IMPLEMENT_SINGLETON_FACTORY(GEObj_Factory)

这样工厂就定义好了:工厂名称为Obj_Factory。可以使用宏REGISTE_OBJ(classname)注册一个具体需要创建的IObj的子类,然后根据注册宏的参数来创建对象。关键是这个宏可以直接写在具体类的cpp文件末尾。例:

/*头文件代码*/

class Text_Obj : public IObj

{

public:

    Text_Obj ();

    ~ Text_Obj();

};

/*cpp文件代码*/

Text_Obj:: Text_Obj ()

{

}

Text_Obj::~ Text_Obj()

{

}

REGISTE_OBJ(Text_Obj)//我喜欢用类名称做码,不会乱,还保证不重复

//cpp结束

然后在应用的地方:

IObj* pObj = Create_GEObj_2Text_Obj);

虽然工厂写起来麻烦一些,但是使用起来却方便。比如,我们写好了抽象对象的序列化,但是读取的时候如何恢复创建对象就可以用此法,只要序列化的时候每个对象都保存一个它的码就行了。关键是,如果我们扩展另外一个对象Circle_Obj,我们只需要注册,不用更改序列化代码。如果Circle_Obj对象在上层库实现,序列化代码在底层库,就更需要了。

另外,代码中T_KeyVector是一个map的封装,理解就好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值