3

考虑到抽象工厂模式,假设您有一个类层次结构,其中具体工厂覆盖 createButton* s * 虚拟方法,需要返回更广泛的按钮数组。由于 C++ 仅支持协变返回类型,有什么优雅的解决方法可以解决这个问题?动态转换?

GoF 示例的修改版本以满足我的要求:

class Button {
public:
        virtual void paint() = 0;
        virtual ~Button(){
        }
};

class WinButton: public Button {
public:
        void paint() {
                cout << "I'm a WinButton";
        }
};

class OSXButton: public Button {
public:
        void paint() {
                cout << "I'm an OSXButton";
        }
};

class GUIFactory {
public:
        virtual Button * createButtons() = 0;
        virtual ~GUIFactory(){
        }
};

class WinFactory: public GUIFactory {
public:
        WinButton* createButtons() {
                return new WinButton[2];
        }

        ~WinFactory(){
        }
};

class OSXFactory: public GUIFactory {
public:
        OSXButton* createButtons() {
                return new OSXButton[2];
        }

        ~OSXFactory(){
        }
};

和应用程序骨架:

Application(GUIFactory * factory) {
                Button* buttons = factory->createButtons();
                for(...) {...}
        }
4

3 回答 3

2

这是不可能的。扪心自问,会来电者delete还是delete[]呢?他们如何知道数组中有多少元素?没有办法用原始指针返回来解决这些问题。因此,对您的问题的简单回答是,这是无法做到的,您甚至也不应该这样做。被调用者需要知道返回类型——是一个按钮还是多个按钮,以及完成后如何清理它们。

如果不调用未定义行为,您甚至无法访问非第一个元素。

工厂应该构造单个对象。如果您需要多个,请多次调用工厂函数。

即使您神奇地拥有可以同时处理多个按钮的代码,而他们只期望一个按钮(wtf?),您也需要安全地返回多个按钮。这意味着std::vector<smart_pointer<Button>>

于 2011-12-23T14:32:40.620 回答
1

不想在工厂方法中创建一个数组并返回一个指向客户端的指针。这样你就不知道有多少按钮,所以你真的不能用你得到的东西做任何事情。

在 C++11 中,您可以返回 astd::vector<shared_ptr<Button>>甚至是std::vector<unique_ptr<Button>>.

不过,我可能会选择此解决方案:返回某种自定义的“只读”Button集合,该集合公开计数和索引器,仅此而已。如果适合您的场景,也许可以添加迭代器。

class ButtonCollection
{
public:
    size_t getCount() const {}
    Button& getAt(size_t index) {}
    const Button& getAt(size_t index) const {}

private:
    friend class GUIFactory;

    ButtonCollection() {}
    add(Button* button) {}
    // Or in C++11:
    // add(std::unique_ptr<Button> button) {}
};

使用您的应用程序框架:

Application(GUIFactory& factory)
{
   std::auto_ptr<ButtonCollection> buttons = factory.createButtons();
   // Or in C++11:
   //std::unique_ptr<ButtonCollection> buttons = factory.createButtons();
   for(...) {...}
}
于 2011-12-23T11:15:32.050 回答
0

考虑使用boost::ptr_vectorboost::ptr_array
http://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_vector.html

于 2011-12-23T14:38:03.613 回答