工厂模式,实现工厂的动态列表

Factory pattern, implementing a dynamic list of factories

本文关键字:工厂 动态 列表 实现 模式      更新时间:2023-10-16

我正在实现一个抽象工厂模式(在 c++ 中),但有一个小问题。

我想避免创建一个在编译时必须知道存在哪些工厂的地方。

通常在示例中,我会看到类似的东西。

Factory * getFactory()
{
    if(/*we should make factoryA*/)
    {
        return FactoryA::instance();
    }
    else if(/*we should return FactoryB*/)
    {
        return FactoryB::instance();
    }
    else
    {
        return NULL;
    }
}

我可以做这样的事情,但我想要更好!

我想到的是工厂基类将有一个工厂列表,从工厂继承的每个类都会创建一个静态实例,并通过工厂中的受保护类函数将该实例添加到列表中。

但是,如果不玩带有静态对象初始化的俄罗斯轮盘赌,我就无法找到一种方法来做到这一点。

为了避免静态初始化顺序出现问题,您可以将列表设置为函数 getFactoryList() 的静态成员。 然后,这将确保当受保护的构造函数需要将工厂添加到列表中时,该列表存在。

然后,您需要将虚拟方法添加到工厂,以确定是否应使用给定的工厂。 希望一次只有一个工厂有资格使用,这样工厂创建的顺序就不会改变返回的工厂。

Somthing Simple:

class BaseFactory
{
    public:
        BaseFactory()
        {
           std::list<BaseFactory*>&  fList = getFactoryList();
           fList.push_back(this);
           // If you are feeling brave.
           // Write the destructor to remove the object from the list.
           //
           // Note C++ guarantees the list will live longer than any of the factories
           // Because the list will always be completely constructed before any
           // of the factory objects (because we get the list in the constructor).
        }
        static BaseFactory& getFactory()  // Don't return a pointer (use a reference)
        {
           std::list<BaseFactory*>&  fList = getFactoryList();
           std::list<BaseFactory*>::iterator i = selectFactory(fList);
           if (i == fList.end()
           {
               static FakeFactory  fakeFactory; // Having a fake factory that
                                                // that returns fake object
                                                // is usually a lot easier than checking for
                                                // NULL factory objects everywhere in the code
                                                //
                                                // Alternatively throw an exception.
               return fakeFactory;
           }
           return *(*i); // return reference
        }
    private:
        static std::list<BaseFactory*>& getFactoryList()
        {
            static std::list<BaseFactory*>  factoryList; // Notice the static
            return factoryList;
        }
};

你会从这样的设计中受益吗?我的意思是,即使你有这个列表,你也必须根据一些标准以某种方式选择那个工厂。

请改为尝试反转控制模式。

如果类 A 需要创建一个对象,请将工厂传递给该类。

class A {
    Factory *f;
 public:
    A(Factory *f)
       : f(f)
    {  }
    void doSomething()
    {
       Object o = f->produce();
        ...
    }
}

然后,您将决定在"更高级别"上使用哪个工厂。工厂可能来自源代码,表单插件等。

我使用一种模式来收集子类的实例。 这是它用工厂来表达的骨架:

class Factory {
    public:
      virtual Foo* makeFoo()=0;
      ...
    protected:
      Factory(){
          getFactoryList().push_back(this);
      }
    private:
      FactoryList& getFactoryList();  // Returns static list
};
class FactoryA: public Factory{
      Foo* makeFoo();  // I make a Foo my way
} FACTORYINSTANCE;

您仍然需要一种方法来搜索列表以查找要使用的正确工厂,而我的宏 FACTORYINSTANCE 只是计算为唯一名称以调用其自己的构造函数。