zoukankan      html  css  js  c++  java
  • c++对象工厂

     

    一.简单工厂

    #pragma once
    
    struct IObjectA
    {
        virtual void Test1()=0;
    };
    
    class ObjectA:public IObjectA
    {
    public:
        virtual void Test1(){}
    };
    
    struct IObjectB
    {
        virtual void Test2()=0;
    };
    
    class ObjectB:public IObjectB
    {
    public:
        virtual void Test2(){}
    };
    
    class ObjectFactory
    {
    public:
        static void Create(int nFlag,void** ppVoid)
        {
            switch (nFlag)
            {
            case 1:
                {
                    IObjectA *pA=new ObjectA;
                    *ppVoid=pA;
                }
                break;
            case 2:
                {
                    IObjectB *pB=new ObjectB;
                    *ppVoid=pB;
                }
                break;
            }
        }
    };
    
    class ObjectTest
    {
    public:
        ObjectTest();
        ~ObjectTest();
    
        static void Test1()
        {
            IObjectA *pA=nullptr;
            ObjectFactory::Create(1,(void**)&pA);
            pA->Test1();
        }
    };
    

    优缺点:这种工厂适用于对象不多的情况下,否则工厂类必须要知道所有类

    对于一个比较大的项目如果有较多的对象就不适合了

    二.使用__uuidof简化类型创建

    借助这个关键字,可以为一个类指定一个guid

    [
        uuid("F5844C2A-50D1-4F2C-85DB-429729927F0F")
    ]
    struct IObjectA
    {
        virtual void Test1()=0;
    };

    如下代码:

        template<typename T>
        static T* Create()
        {
            GUID id=__uuidof(T);
            if(IsEqualGUID(id,__uuidof(IObjectA)))
            {
                IObjectA *pA=new ObjectA;
                return (T*)pA;
            }    
            else if(IsEqualGUID(id,__uuidof(IObjectB)))
            {
                IObjectB *pB=new ObjectB;
                return (T*)pB;
            }
            return nullptr;
        }
    
        static void Test2()
        {
            IObjectA *pA=ObjectFactory::Create<IObjectA>();
            pA->Test1();
        }

    以上的使用方式对外确实便利了很多

    下面来解决if else的问题,

    三.使用map来存储

    1.由于map要使用guid来作为key,那么就需要一个比较函数

    来看一下IsEqualGUID的实现,实际是一个宏,对字符串的比较

    __inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
    {
        return !memcmp(&rguid1, &rguid2, sizeof(GUID));
    }

    2.为了可以灵活创建对象,我们可以使用函数指针来创建对象

    基于以上2点,我们创建来以下数据结构

        typedef void (*CreateFunc)(void** ppVoid);
        struct guidCompare
        {
            bool operator () (GUID rguid1,GUID rguid2) const
            {
                return memcmp(&rguid1, &rguid2, sizeof(GUID))< 0;
            }
        };
        static std::map<GUID,CreateFunc,guidCompare> m_mapObj;

    接着要初始化各个对象的创建函数

        template<typename T,typename I>
        static void CreateInstance(void** ppVoid)
        {
            I *pObject=new T;
            *ppVoid=pObject;
        }
        
        static void Init()
        {
            m_mapObj.insert(std::map<GUID,CreateFunc>::value_type
                (__uuidof(IObjectA),CreateInstance<ObjectA,IObjectA>));
            m_mapObj.insert(std::map<GUID,CreateFunc>::value_type
                (__uuidof(IObjectB),CreateInstance<ObjectB,IObjectB>));
        }

    3.再次改造一个Create方法

        template<typename T>
        static T* CreateFromMap()
        {
            GUID id=__uuidof(T);
    
            std::map<GUID,CreateFunc>::iterator iter=m_mapObj.find(id);
            if(iter!=m_mapObj.end())
            {
                T* pObject=NULL;
                iter->second((void**)&pObject);
                return pObject;
            }
    
            return nullptr;
        }

    4.测试代码

        static void Test3()
        {
            ObjectFactory::Init();
            IObjectA *pA=ObjectFactory::CreateFromMap<IObjectA>();
            pA->Test1();
        }

    以上步骤不再用一个一个的判断对象的guid,唯一的问题点在于初始化的问题

    四.借助全局对象初始化来注册

    封装一个Register方法

        template<typename T,typename I>
        static void Register()
        {
            m_mapObj.insert(std::map<GUID,CreateFunc>::value_type
                (__uuidof(I),CreateInstance<T,I>));
        }
    
        Register<ObjectA,IObjectA>();

    如果直接全局来调用这个方法的话显的有些暴力,而且容易出错,重复注册,可以借助一个辅助类在构造函数内完成

    class ObjectACreateHelper
     {
     public:
         ObjectACreateHelper()
         {
             ObjectFactory::Register<ObjectA,IObjectA>();
         }
     };
     class ObjectBCreateHelper
     {
     public:
         ObjectBCreateHelper()
         {
             ObjectFactory::Register<ObjectB,IObjectB>();
         }
     };
     ObjectACreateHelper g_ObjectACreateHelper;
     ObjectBCreateHelper g_ObjectBCreateHelper;

    上面的代码就完成的差不多了,上面的代码就是力气活来,可以再想办法简化

    五.使用宏和模板来简化注册

    template<typename T,typename I>
    class CObjectCreateHelper
    {
    public:
        CObjectCreateHelper()
        {
            ObjectFactory::Register<T,I>();
        }
    };
    
    #define REG_CREATEObject(T, I) CObjectCreateHelper<T,I> g_##T;
    
    REG_CREATEObject(ObjectA,IObjectA)
    REG_CREATEObject(ObjectB,IObjectB)

    现在就全部完成了整个步骤的改造,此思想可以用到很多类似的对象创建方法,很管用

  • 相关阅读:
    HDU 2844 Coins(多重背包)
    HDU 4540 威威猫系列故事——打地鼠(DP)
    Codeforces Round #236 (Div. 2)
    FZU 2140 Forever 0.5
    HDU 1171 Big Event in HDU(DP)
    HDU 1160 FatMouse's Speed(DP)
    ZOJ 3490 String Successor
    ZOJ 3609 Modular Inverse
    ZOJ 3603 Draw Something Cheat
    ZOJ 3705 Applications
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/3407662.html
Copyright © 2011-2022 走看看