C++ 如何设计一个简单的C++;对象工厂?

C++ 如何设计一个简单的C++;对象工厂?,c++,factory,C++,Factory,在我的应用程序中,有10-20个类被实例化一次[*]。下面是一个例子: class SomeOtherManager; class SomeManagerClass { public: SomeManagerClass(SomeOtherManager*); virtual void someMethod1(); virtual void someMethod2(); }; 类的实例包含在一个对象中: class TheManager { public: vi

在我的应用程序中,有10-20个类被实例化一次[*]。下面是一个例子:

class SomeOtherManager;

class SomeManagerClass {
public:
    SomeManagerClass(SomeOtherManager*);
    virtual void someMethod1();
    virtual void someMethod2();
};
类的实例包含在一个对象中:

class TheManager {
public:
    virtual SomeManagerClass* someManagerClass() const;
    virtual SomeOtherManager* someOtherManager() const;
    /** More objects... up to 10-20 */
};
当前,管理器使用新操作符来创建对象

我的目的是能够使用插件将SomeManagerClass(或任何其他类)实现替换为另一个实现。为了替代实施,需要两个步骤:

  • 定义派生的SomeManagerClass类,该类继承SomeManagerClass[插件]
  • 创建新类(DerivedSomeManagerClass)而不是默认类(SomeManagerClass)[应用程序]
  • 我想我需要某种对象工厂,但它应该相当简单,因为总是只有一种类型要创建(默认实现或用户实现)

    你知道如何设计一个像我刚才描述的简单工厂吗?考虑将来可能有更多类的事实,所以它应该易于扩展。

    [*]我不在乎它是否不止发生一次


    编辑:请注意,Manager中包含两个以上的对象。

    您可以使用返回Manager类实例的静态方法实现对象工厂。在工厂中,您可以为默认类型的管理器创建一个方法,也可以为任何类型的管理器创建一个方法,您可以为这些管理器提供一个表示管理器类类型的参数(比如使用枚举)。最后一个方法应该返回接口而不是类

    <>编辑:我会尝试给出一些代码,但是要注意我的C++时间相当长,我现在只做java和一些脚本。
    class Manager { // aka Interface
        public: virtual void someMethod() = 0;
    };
    
    class Manager1 : public Manager {
        void someMethod() { return null; }
    };
    
    class Manager2 : public Manager {
        void someMethod() { return null; }
    };
    
    enum ManagerTypes {
        Manager1, Manager2
    };
    
    class ManagerFactory {
        public static Manager* createManager(ManagerTypes type) {
            Manager* result = null;
            switch (type) {
            case Manager1:
                 result = new Manager1();
                 break;
            case Manager2:
                 result = new Manager2();
                 break;
            default:
                 // Do whatever error logging you want
                 break;
            }
            return result;
         }
     };
    
    现在,您应该能够通过(如果您已经能够使代码示例正常工作)呼叫工厂:


    这是我想到的解决方案,它不是最好的,但也许它有助于想出更好的解决方案:

    每个类都有一个creator类:

    class SomeManagerClassCreator {
    public:
        virtual SomeManagerClass* create(SomeOtherManager* someOtherManager) { 
            return new SomeManagerClass(someOtherManager); 
        }
    };
    
    然后,创建者将聚集在一个类中:

    class SomeManagerClassCreator;
    class SomeOtherManagerCreator;
    
    class TheCreator {
    public:
        void setSomeManagerClassCreator(SomeManagerClassCreator*);
        SomeManagerClassCreator* someManagerClassCreator() const;
    
        void setSomeOtherManagerCreator(SomeOtherManagerCreator*);
        SomeOtherManagerCreator* someOtherManagerCreator() const;
    private:
        SomeManagerClassCreator* m_someManagerClassCreator;
        SomeOtherManagerCreator* m_someOtherManagerCreator;
    };
    
    管理者将与创建者一起创建,用于内部创建:

    class TheManager {
    public:
        TheManager(TheCreator*);
        /* Rest of code from above */
    };
    

    这个解决方案的问题是它违反了DRY——对于每个类创建者,我都必须在创建者中编写setter/getter。

    Mh我没有百分之百的理解,我也不太喜欢书本和文章中的工厂内容


    如果您的所有经理共享一个类似的接口,您可以从基类派生,并在程序中使用该基类。 根据将创建哪个类的决策将在何处做出,您必须使用标识符进行创建(如上所述),或者处理要在内部实例化哪个管理器的决策


    另一种方法是像使用模板一样实现it“策略”。因此,您可以使用ManagerClass::create()返回特定的SomeOtherManagerWhatver实例。这将在使用您的经理的代码中确定要由哪个经理做出决定-可能这不是故意的

    或者这样:


    模板
    类MyAwesomeClass
    {
    记忆管理m_记忆管理者;
    };
    
    (或诸如此类) 使用此构造,您只需更改MyAwesomeClass的实例化即可轻松使用其他管理器


    同样,用于此目的的类可能有点过头了。在您的情况下,我想工厂函数就可以了。嗯,这更多的是个人偏好的问题。

    我会创建一个“基本”工厂,它有虚拟方法来创建所有基本管理器,并让“元管理器”(您问题中的管理器)将指向基本工厂的指针作为构造函数参数

    我假设“工厂”可以通过从CXYZWManager派生来自定义CXYZWManager的实例,但CXYZWManager的构造函数也可以在“自定义”工厂中使用不同的参数

    输出“CSomeManager”和“cderivedfromomemanager”的冗长代码示例:

    #包括
    //--------------------------------------------------------------------------------
    班级经理
    {
    公众:
    virtual const char*ShoutOut(){return“CSomeManager”;}
    };
    //--------------------------------------------------------------------------------
    类协同热管理器
    {
    };
    //--------------------------------------------------------------------------------
    类管理器工厂
    {
    公众:
    //非静态、非常量以允许多态性滥用
    虚拟CSomeManager*CreateSomeManager(){返回新CSomeManager();}
    虚拟协同管理器*CreateOtherManager(){返回新协同管理器();}
    };
    //--------------------------------------------------------------------------------
    类CDerivedFromSomeManager:公共CSomeManager
    {
    公众:
    virtual const char*ShoutOut(){返回“CDerivedFromSomeManager”;}
    };
    //--------------------------------------------------------------------------------
    为CustomManagerFactory类:public TheManagerFactory
    {
    公众:
    虚拟CDerivedFromSomeManager*CreateSomeManager(){返回新的CDerivedFromSomeManager();}
    };
    //--------------------------------------------------------------------------------
    类管理器
    {
    公众:
    CMETA经理(管理工厂*ip_工厂)
    :mp\u some\u manager(ip\u工厂->CreateSomeManager()),
    mp_其他_管理器(ip_工厂->CreateOtherManager())
    {}
    CSomeManager*GetSomeManager(){return mp\u some\u manager;}
    COtherManager*GetOtherManager(){return mp_other_manager;}
    私人:
    CSomeManager*mp_some_manager;
    共同经理*mp_其他_经理;
    };
    //--------------------------------------------------------------------------------
    int _tmain(int argc,_TCHAR*argv[]
    {
    管理工厂标准工厂;
    客户经理工厂客户工厂;
    CMetaManager meta_manager_1(和标准_工厂);
    CMetaManager meta_manager_2(和定制工厂);
    
    std::cout ShoutOut()我会使用这样的模板,因为我看不见
    class TheManager {
    public:
        TheManager(TheCreator*);
        /* Rest of code from above */
    };
    
    template<class MemoryManagment>
    class MyAwesomeClass
    {
        MemoryManagment m_memoryManager;
    };
    
    #include <iostream>
    //--------------------------------------------------------------------------------
    class CSomeManager
      {
      public:
        virtual const char * ShoutOut() { return "CSomeManager";}
      };
    
    //--------------------------------------------------------------------------------
    class COtherManager
      {
      };
    
    //--------------------------------------------------------------------------------
    class TheManagerFactory
      {
      public:
        // Non-static, non-const to allow polymorphism-abuse
        virtual CSomeManager   *CreateSomeManager() { return new CSomeManager(); }
        virtual COtherManager  *CreateOtherManager() { return new COtherManager(); }
      };
    
    //--------------------------------------------------------------------------------
    class CDerivedFromSomeManager : public CSomeManager
      {
      public:
        virtual const char * ShoutOut() { return "CDerivedFromSomeManager";}
      };
    
    //--------------------------------------------------------------------------------
    class TheCustomManagerFactory : public TheManagerFactory
      {
      public:
        virtual CDerivedFromSomeManager        *CreateSomeManager() { return new CDerivedFromSomeManager(); }
    
      };
    
    //--------------------------------------------------------------------------------
    class CMetaManager
      {
      public:
        CMetaManager(TheManagerFactory *ip_factory)
          : mp_some_manager(ip_factory->CreateSomeManager()),
            mp_other_manager(ip_factory->CreateOtherManager())
          {}
    
        CSomeManager  *GetSomeManager()  { return mp_some_manager; }
        COtherManager *GetOtherManager() { return mp_other_manager; }
    
      private:
        CSomeManager  *mp_some_manager;
        COtherManager *mp_other_manager;
      };
    
    //--------------------------------------------------------------------------------
    int _tmain(int argc, _TCHAR* argv[])
      {
      TheManagerFactory standard_factory;
      TheCustomManagerFactory custom_factory;
    
      CMetaManager meta_manager_1(&standard_factory);
      CMetaManager meta_manager_2(&custom_factory);
    
      std::cout << meta_manager_1.GetSomeManager()->ShoutOut() << "\n";
      std::cout << meta_manager_2.GetSomeManager()->ShoutOut() << "\n";
      return 0;
      }
    
    class SomeOtherManager;
    
    class SomeManagerClass {
    public:
        SomeManagerClass(SomeOtherManager*);
        virtual void someMethod1();
        virtual void someMethod2();
    };
    
    
    class TheBaseManager {
    public:
          // 
    };
    
    template <class ManagerClassOne, class ManagerClassOther> 
    class SpecialManager : public TheBaseManager {
        public:
            virtual ManagerClassOne* someManagerClass() const;
            virtual ManagerClassOther* someOtherManager() const;
    };
    
    TheBaseManager* ourManager = new SpecialManager<SomeManagerClass,SomeOtherManager>;
    
    class Manager
    {
    public:
      virtual void doSomething() = 0;
      virtual int doSomethingElse() = 0;
    }
    
    extern "C" {
    Manager* newManager();
    void deleteManager(Manager*);
    }
    
    #include "Manager.h"
    
    class PluginManager : public Manager
    {
    public:
      PluginManager();
      virtual ~PluginManager();
    
    public:
      virtual void doSomething();
      virtual int doSomethingElse();
    }
    
    #include "PluginManager.h"
    
    Manager* newManager()
    {
      return new PluginManager();
    }
    void deleteManager(Manager* pManager)
    {
      delete pManager;
    }
    
    PluginManager::PluginManager()
    {
      // ...
    }
    
    PluginManager::~PluginManager()
    {
      // ...
    }
    
    void PluginManager::doSomething()
    {
      // ...
    }
    
    int PluginManager::doSomethingElse()
    {
      // ...
    }
    
    class factory
    {
    public:
        virtual SomeManagerClass* create() = 0;
    };
    
    class plugin1_factory : public factory
    {
    public:
        SomeManagerClass* create() { return new plugin1(); }
    };
    
    std::map<string, factory*>  factory_map;
    ...
    factory_map["plugin1"] = new plugin1_factory();
    
    SomeManagerClass* obj = factory_map[plugin_name]->create();
    
    template <class plugin_type>
    class plugin_factory : public factory
    {
    public:
       SomeManagerClass* create() { return new plugin_type(); }
    };
    
    factory_map["plugin1"] = new plugin_factory<plugin1>();
    
    class IFrameWork { public: virtual ~IFrameWork() {} virtual void RegisterInterface( const char*, void* ) = 0; virtual void* GetInterface( const char* name ) = 0; }; class IPlugIn { public: virtual ~IPlugIn() {} virtual void BindInterfaces( IFrameWork* frameWork ) {}; virtual void Start() {}; virtual void Stop() {}; }; struct SamplePlugin :public IPlugIn { ILogger* logger; Component1 component1; WebServer webServer; public: SamplePlugin( IFrameWork* frameWork ) :logger( (ILogger*)frameWork->GetInterface( "ILogger" ) ), //assumes the 'System' plugin exposes this component1(), webServer( component1 ) { logger->Log( "MyPlugin Ctor()" ); frameWork->RegisterInterface( "ICustomerManager", dynamic_cast( &component1 ) ); frameWork->RegisterInterface( "IVendorManager", dynamic_cast( &component1 ) ); frameWork->RegisterInterface( "IAccountingManager", dynamic_cast( &webServer ) ); } virtual void BindInterfaces( IFrameWork* frameWork ) { logger->Log( "MyPlugin BindInterfaces()" ); IProductManager* productManager( static_cast( frameWork->GetInterface( "IProductManager" ) ) ); IShippingManager* shippingManager( static_cast( frameWork->GetInterface( "IShippingManager" ) ) ); component1.BindInterfaces( logger, productManager ); webServer.BindInterfaces( logger, productManager, shippingManager ); } virtual void Start() { logger->Log( "MyPlugin Start()" ); webServer.Start(); } virtual void Stop() { logger->Log( "MyPlugin Stop()" ); webServer.Stop(); } }; class FrameWork :public IFrameWork { vector plugIns; map interfaces; public: virtual void RegisterInterface( const char* name, void* itfc ) { interfaces[ name ] = itfc; } virtual void* GetInterface( const char* name ) { return interfaces[ name ]; } FrameWork() { //Only interfaces in 'SystemPlugin' can be used by all methods of the other plugins plugIns.push_back( new SystemPlugin( this ) ); plugIns.push_back( new SamplePlugin( this ) ); //add other plugIns here for_each( plugIns.begin(), plugIns.end(), bind2nd( mem_fun( &IPlugIn::BindInterfaces ), this ) ); for_each( plugIns.begin(), plugIns.end(), mem_fun( &IPlugIn::Start ) ); } ~FrameWork() { for_each( plugIns.rbegin(), plugIns.rend(), mem_fun( &IPlugIn::Stop ) ); for_each( plugIns.rbegin(), plugIns.rend(), Delete() ); } };
    #include "stdafx.h"
    #include <map>
    #include <string>
    
    class BaseClass
    {
    public:
        virtual ~BaseClass() { }
        virtual void Test() = 0;
    };
    
    class DerivedClass1 : public BaseClass 
    { 
    public:
        virtual void Test() { } // You can put a breakpoint here to test.
    };
    
    class DerivedClass2 : public BaseClass 
    { 
    public:
        virtual void Test() { } // You can put a breakpoint here to test.
    };
    
    class IFactory
    {
    public:
        virtual BaseClass* CreateNew() const = 0;
    };
    
    template <typename T>
    class Factory : public IFactory
    {
    public:
        T* CreateNew() const { return new T(); }
    };
    
    class FactorySystem
    {
    private:
        typedef std::map<std::wstring, IFactory*> FactoryMap;
        FactoryMap m_factories;
    
    public:
        ~FactorySystem()
        {
            FactoryMap::const_iterator map_item = m_factories.begin();
            for (; map_item != m_factories.end(); ++map_item) delete map_item->second;
            m_factories.clear();
        }
    
        template <typename T>
        void AddFactory(const std::wstring& name)
        {
            delete m_factories[name]; // Delete previous one, if it exists.
            m_factories[name] = new Factory<T>();
        }
    
        BaseClass* CreateNew(const std::wstring& name) const
        {
            FactoryMap::const_iterator found = m_factories.find(name);
            if (found != m_factories.end())
                return found->second->CreateNew();
            else
                return NULL; // or throw an exception, depending on how you want to handle it.
        }
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        FactorySystem system;
        system.AddFactory<DerivedClass1>(L"derived1");
        system.AddFactory<DerivedClass2>(L"derived2");
    
        BaseClass* b1 = system.CreateNew(L"derived1");
        b1->Test();
        delete b1;
        BaseClass* b2 = system.CreateNew(L"derived2");
        b2->Test();
        delete b2;
    
        return 0;
    }
    
    class ManagerFactory
    {
    public:
        template <typename T> static BaseManager * getManager() { return new T();}
    };
    
    BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
    
    #include <map>
    #include <string>
    
    class BaseManager
    {
    public:
        virtual void doSomething() = 0;
    };
    
    class DerivedManager1 : public BaseManager
    {
    public:
        virtual void doSomething() {};
    };
    
    class DerivedManager2 : public BaseManager
    {
    public:
        virtual void doSomething() {};
    };
    
    class ManagerFactory
    {
    public:
        typedef BaseManager * (*GetFunction)();
        typedef std::map<std::wstring, GetFunction> ManagerFunctionMap;
    private:
        static ManagerFunctionMap _managers;
    
    public:
        template <typename T> static BaseManager * getManager() { return new T();}
        template <typename T> static void registerManager(const std::wstring& name)
        {
            _managers[name] = ManagerFactory::template getManager<T>;
        }
        static BaseManager * getManagerByName(const std::wstring& name)
        {
            if(_managers.count(name))
            {
                return _managers[name]();
            }
            return NULL;
        }
    };
    // the static map needs to be initialized outside the class
    ManagerFactory::ManagerFunctionMap ManagerFactory::_managers;
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        // you can get with the templated function
        BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
        manager1->doSomething();
        // or by registering with a string
        ManagerFactory::template registerManager<DerivedManager1>(L"Derived1");
        ManagerFactory::template registerManager<DerivedManager2>(L"Derived2");
        // and getting them
        BaseManager * manager2 = ManagerFactory::getManagerByName(L"Derived2");
        manager2->doSomething();
        BaseManager * manager3 = ManagerFactory::getManagerByName(L"Derived1");
        manager3->doSomething();
        return 0;
    }