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

发布于 2024-11-05 04:41:38 字数 539 浏览 0 评论 0原文

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

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

通常在示例中我会看到类似的内容。

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

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

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

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

I'm implementing an abstract factory pattern (in c++), but there is a slight problem.

I'd like to avoid creating a place which must know at compile time what factories exist.

Usually in the examples I see something like this.

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

I could do something like this, but I want better!

What I have in mind is that the Factory base class would have a list of Factories, each class inherited from Factory would create a static instance and add that instance to the list, through a protected class function in Factory.

However, I can't figure out a way to do this without playing Russian Roulette with static object initialization.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅浅淡淡 2024-11-12 04:41:38

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

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

To avoid problems with static initialization order, you can make the list a static member of a function getFactoryList(). This will then ensure that the list exists when the protected constructor needs to add a factory to the list.

You'll then want to add a virtual method to Factory to determine if a given factory should be used. Hopefully only one factory is eligible for use at a time, so that the order that the factories got created does not change which factory is returned.

闻呓 2024-11-12 04:41:38

事情很简单:

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

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;
        }
};
ゝ杯具 2024-11-12 04:41:38

这样的设计会给您带来什么好处?我的意思是,即使您有该列表,您也必须根据某些标准以某种方式选择该工厂。

尝试使用控制反转模式。

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

class A {
    Factory *f;
 public:
    A(Factory *f)
       : f(f)
    {  }

    void doSomething()
    {
       Object o = f->produce();
        ...
    }
}

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

How would you benefit form such design? I mean, even when you had that list, you would have to select that factory somehow, based on some criteria.

Try Inversion Of Control pattern instead.

If Class A needs to create an object, pass factory to that class.

class A {
    Factory *f;
 public:
    A(Factory *f)
       : f(f)
    {  }

    void doSomething()
    {
       Object o = f->produce();
        ...
    }
}

Then you would decide which factory to use on the "higher level". Factory may came form the source, form plugin etc.

画▽骨i 2024-11-12 04:41:38

我使用一种模式来收集子类的实例。这是它以工厂的形式表达的基本内容:

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 只是计算一个唯一的名称,以便调用它自己的构造函数。

I use a pattern to collect instances of subclasses. This is the bare bones of it couched in terms of a factory:

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;

You still need a way of searching the list for the correct factory to use, and my macro FACTORYINSTANCE just evaluates to a unique name in order to invoke its own constructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文