在我的申请中,有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 */
};

目前TheManager使用 新的 操作员,以便创造的对象。

我的意向是要能够替换使用的插件,SomeManagerClass(或任何其他类别)的执行与另外一个。为了替换执行,2个步骤是需要的:

  1. 定义一类DerivedSomeManagerClass,其继承SomeManagerClass[插件]
  2. 创建新类(DerivedSomeManagerClass),而不是默认(SomeManagerClass)[程序]

我猜我需要一些对象的种类的工厂,但是它应该是相当简单,因为那里始终是只有一种类型创建(默认的执行情况或用户的实现)。

任何想法,关于如何设计一种简单的工厂就像我刚才描述的?考虑的事实,可能会有更多的类的未来,因此应该可以很容易地延伸。

[*]我不在乎如果发生这种情况超过一次。

编辑: 请注意,有超过两个对象是包含在TheManager.

有帮助吗?

解决方案

我认为有两个单独的问题在这里。

一个问题是:怎么TheManager 名称 类,它已经创建?它必须保持某种形式的指"一种方式来创建的类"。可能的解决方案是:

  • 保持一个单独的针对每一种类的一种方式设定它,但是你已经说你不喜欢这样,因为它违反了干原则
  • 保持某种形式的表,其中关键的是一枚举或一串;在这种情况下的定者是一个单一的职能与参数(当然,如果关键的是一个枚举,可以使用一种矢量,而不是一张地图)

另一个问题是:这是什么"的方式来创建一个类"?不幸的是,我们不能储存指直接造,但我们可以:

  • 创建,正如其他人指出的那样,一个工厂的每一类
  • 只是添加一个静态"创建的"功能为每一类;如果他们保持一致的签名,你就可以使用他们指针的功能

模板可能有助于避免不必要的重复代码在两种情况。

其他提示

假设一类(plugin1)其继承SomeManagerClass,你需要一个类的分级结构来建立您的种类型:

class factory
{
public:
    virtual SomeManagerClass* create() = 0;
};

class plugin1_factory : public factory
{
public:
    SomeManagerClass* create() { return new plugin1(); }
};

然后你可以指定这些工厂std::地图上,在那里他们一定会串

std::map<string, factory*>  factory_map;
...
factory_map["plugin1"] = new plugin1_factory();

最后你TheManager只是需要知道姓名的插件(string),并可以回返的一个目的类型SomeManagerClass只有一行代码:

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>();

我认为这是一个更好的解决方案。此外,'plugin_factory'类可能会增加本身的'factory_map'如果你通过costructor string.

我已经回答了在另一个这样的问题,关于用C++的工厂。请看看 还有 如果一个灵活的工厂的兴趣。我尝试描述一个古老的方式,从ET++使用宏其具有伟大的工作对我来说。

ET++ 是一个项目,以口老MacApp C++和X11。在努力为它埃里克*伽玛等等开始思考 设计图案

我想创建一个"基地"工厂,具有虚拟的方法,为创造所有的基本管理人员,并让"元manager"(TheManager在你的问题)采取一指针为基厂作为一种构造的参数。

我假设,"工厂"可以定制的实例CXYZWManager通过源自他们的,但是可选的构造CXYZWManager可以采取不同的参数,在"定义"工厂。

一个冗长的代码如,输出"CSomeManager"和"CDerivedFromSomeManager":

#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 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;
};

和TheManager将创建是实物比特币的创造者,内部创建:

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

这种解决方案的问题是,它违反了干的每一类的创造者,我会写入器/气剂在是实物比特币的创造者,.

这似乎是这将是一个很简单的功能的模板而不是一个抽象的工厂的图案

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;
}

编辑:在阅读其他的答案,我意识到,这是非常相似戴维Van den Eynde的FactorySystem的解决方案,但是,我使用一个功能的模板的指针,而不是实例化模板工厂课程。我觉得我的解决方案是一个小更轻巧。由于静态功能,唯一目的,获取实例是地图本身。如果你需要的工厂,以执行其他功能(DestroyManager,等等), 我认为他的解决方案是多个可扩展的。

你可以实现的一个目厂以静态的方法,返回的一个实例,一名经理。在工厂您可以创建一种默认的种类型的管理和方法用于任何类型的经理,你得到一个参数表示的种类型的管理级(说有一枚举).最后这个方法应该返回一个接口,而不是一类。

编辑:我会尽量给予一些代码,但是记住,我的C++时间相当长一段时间后和我做的只爪哇和一些脚本。

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;
     }
 };

现在你应该可以打电话给工厂通过(如果你已经能够使代码样的工作):

Manager* manager = ManagerFactory.createManager(ManagerTypes.Manager1);

我会使用的模板,这样我看不到这一点的工厂类:

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>;

你应该看看的教程 http://downloads.sourceforge.net/papafactory/PapaFactory20080622.pdf?use_mirror=fastbull

它包含一个伟大的教程在实施一个抽象的工厂C++的,源代码来与它也是非常强大

克里斯

Mh我不明白一个百分之百,我不是真的进入工厂的东西从书本和文章。


如果所有管理人员分享一个类似的接口,你可能源自一个基础课,并利用这个基础课在你的节目。这取决于决定哪一类将创建,将成,你有使用标识制作(如上文所述),或者处理的决定,其管理的实例。


另一种方法是实施它的"政策"通过使用模板。所以,你ManagerClass::create()返回的一个具体SomeOtherManagerWhatever的实例。这将奠定决定其管理使在代码,它使用你的经理-Maye这不是目的。

或那样的方式:


template<class MemoryManagment>
class MyAwesomeClass
{
    MemoryManagment m_memoryManager;
};

(或类似的东西) 这个构造你可以很容易地使用其他管理人员通过仅仅改变化的MyAwesomeClass.


还有一类适用于这一目的也许是一点在上面。在你的情况下,一个工厂的功能要做的,我猜。以及它的更是一个问题的个人的偏好。

如果你计划支持的插件,是动态的联系,你的计划将需要提供一个稳定的阿比(应用程序接口),意味着不能使用C++作为你的主要接口C++没有标准ABI。

如果你想插件,以实现一个接口,你定义自己的,你会需要提供标题的文件的界面插件的程序和标准化上的一个非常简单的C界面,以创建和删除的对象。

您不能提供一个动态库,将让你的"新"的插件类。这就是为什么你需要标准化C界面,以便创造的对象。使用C++对象是那么可能的,只要没有你的参数使用可能不相容的类型,例如限制集装箱。你将不能使用矢量返回的另一个库,因为不能确保他们的STL执行情况是一样的你。

经理。h

class Manager
{
public:
  virtual void doSomething() = 0;
  virtual int doSomethingElse() = 0;
}

extern "C" {
Manager* newManager();
void deleteManager(Manager*);
}

PluginManager.h

#include "Manager.h"

class PluginManager : public Manager
{
public:
  PluginManager();
  virtual ~PluginManager();

public:
  virtual void doSomething();
  virtual int doSomethingElse();
}

PluginManager.cpp

#include "PluginManager.h"

Manager* newManager()
{
  return new PluginManager();
}
void deleteManager(Manager* pManager)
{
  delete pManager;
}

PluginManager::PluginManager()
{
  // ...
}

PluginManager::~PluginManager()
{
  // ...
}

void PluginManager::doSomething()
{
  // ...
}

int PluginManager::doSomethingElse()
{
  // ...
}

你没有谈TheManager.它看起来像你想要得到控制这类正在使用?或者,也许你试图把它们在一起吗?

它听起来你需要一个抽象的基类和一个指目前使用的类。如果你想链你可以做到在两个抽象的类和themanager类。如果抽象的类,添加一个成员,以下一级的链条,如果themanager然后排序以你其使用在一个列表。你会需要的方式来增加课所以你需要一个议addme()在themanager.这听起来像你知道你这样做w/e你选择应该是正确的。一个列表与议addme func是我的建议如果你想要的只有1个活动类然后一个功能在TheManager决定这将是一件好事。

这可能比你更重要,但它听起来你正在尝试做一个框架的工作类支持的插件。

我要打破它以3个部分。

1)框架类会自己的插件。此类是负责发布的接口提供的插件。

2)一个插件类会自己的组件,做的工作。此类是负责登记出口的接口和结合进口的接口组成。

3)的第三部分,组件是该供应商和消费者的接口。

做事情可扩展的,得到的东西并运行可能爆发成阶段。

  1. 创造的一切。
  2. 线的一切。
  3. 开始一切。

要打破东西了。

  1. 停止一切。
  2. 摧毁一切。
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() );
    }
};

这里是最小的工厂模式实施,我提出了在大约15分钟。我们用一个类似的使用更先进的基础课程。

#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;
}

只是复制、粘贴在初始Win32控制台应用程序在VS2005/2008年。我想指出的东西:

  • 你不需要创建一个混凝土工厂的每一类。一个模板会为你做的。
  • 我喜欢的地方整个工厂模式在其类别,因此,你不需要担心创造工厂的目的和删除它们。你只需登记您的课程,一个工厂类被创造的编译器和工厂对象得到创建模式。在其寿命、所有工厂都是干净的破坏。我喜欢这种形式的封装,因为没有困惑过谁管辖的使用寿命的工厂。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top