如何优雅地处理抽象工厂和数组作为C ++中的返回类型?

时间:2011-12-23 11:01:28

标签: c++ covariance abstract-factory

考虑到抽象工厂模式,假设你有一个class hierarchy具体工厂覆盖createButton * s *虚方法,需要返回更多的按钮。有什么可以解决这个问题的优雅解决方法,因为C ++只支持协变返回类型?的dynamic_cast?

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(...) {...}
        }

3 个答案:

答案 0 :(得分:2)

无法做到。问问自己,来电者是delete还是delete[]?他们如何知道阵列中有多少元素?使用原始指针返回无法解决这些问题。所以对你的问题的简单回答是,这是不可能做到的,你甚至不想这样做。被调用者需要知道返回类型 - 无论是一个按钮还是多个按钮,以及如何在完成后清理它们。

如果不调用未定义的行为,您甚至无法访问非首位元素。

工厂应该构建单个对象。如果您需要多个,请多次调用出厂功能。

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

答案 1 :(得分:1)

想要在工厂方法中创建数组并返回指向客户端的指针。这样你就可以知道有多少个按钮,所以你真的无法做任何事情。

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

我可能会选择这个解决方案:返回某种自定义的“readonly”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(...) {...}
}

答案 2 :(得分:0)

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