笔记应用的类结构

时间:2013-12-06 15:34:57

标签: c++ oop design-patterns

大家好!

我正在编写一个小应用程序来保存不同的注释(备忘录),并且有一个我不喜欢的类结构。我在核心中有一个 core :: MemoInterface 和一个 core :: MemoBuilder 类(实现并不重要)。然后在GUI中我有一些真正的备忘录类(例如: SimpleMemo TodoMemo 等......)知道如何绘制自己和派生自 gui :: MemoInterace gui :: TabsBuilder ,它在窗口中创建一个新选项卡,并请求每个备忘录在新创建的选项卡中绘制自己。

在我的实现中, gui :: TabsBuilder :: Build()调用 gui :: MemoBuilder :: Build()并尝试使用dynamic_cast来理解MemoInterface来自GUI。 实际上这是我不喜欢的时刻,问题是如何改进或重写core :: MemoBuilder对GUI没有任何了解的结构,但是可以请求每个备忘录自己绘制

对不起,如果不是很清楚。以下代码可能使它更容易理解。

namespace core {
class MemoInterface {
};

class MemoStorage { ... };

class MemoBuilder {
public:
    ... some code ...
    virtual MemoInterface* Build();
private:
    MemoStorage& storage_; // put here all created MemoInterface objects
};
} // namespace

namespace gui {
class MemoInterface : public core::MemoInterface {
public:
    virtual void Draw(SomeWindowClass* dst) = 0;
};
class SimpleMemo : public MemoInterface { // draw implementation };
class TodoMemo : public MemoInterface { };

class TabsBuilder : public core::MemoBuilder {
public:
    ... some code ...

    virtual core::MemoInterface* Build() {
         // I don't like dynamic_cast, think that it's not a good oop way 
         gui::MemoInterface* memo = dynamic_cast<gui::MemoInterface*>core::MemoBuilder::Build();

        if (!memo)
            throw std::exception();

        memo->Draw(wnd_); // or Draw(wnd_->createNestedTab()->window()) it doesn't matter

        return memo;
    }

private:
    SomeWindowClass* wnd_;
};

} // namespace gui

1 个答案:

答案 0 :(得分:0)

我假设dynamic_cast的模板参数是gui :: MemoInterface *,而不是core :: MemoInterface *,因为core :: MemoBuilder :: Build()已经返回core :: MemoInterface *。

从你的代码中可以看出,SimpleMemo和TodoMemo之间的唯一区别是可视化的,因为它们都是同一个基类的子类。 core :: MemoInterface中是否有一些成员数据区分SimpleMemo和TodoMemo?

似乎我有更多的问题/假设而不是答案,所以这里有一个建议:使SimpleMemo和core :: MemoInterface之间的关系成为HAS-A(包含)。如果你愿意,你仍然可以从gui :: MemoInterface派生SimpleMemo。为TodoMemo做同样的事情。然后定义一个工厂方法,该方法将core :: MemoInterface *作为参数。它根据提供的核心:: MemoInterface *中的信息创建适当类型的备忘录(SimpleMemo或TodoMemo):

class GuiMemoCreator
{
public:
    static gui::MemoInterface* CreateGuiMemo(core::MemoInterface* pMemo)
    {
        gui::MemoInterface* pGuiMemo = NULL;
        if ( pMemo->_id == SIMPLE )
        {
            pGuiMemo = new SimpleMemo(pMemo);
        }
        else if ( pMemo->_id == TODO )
        {
            pGuiMemo = new TodoMemo(pMemo);
        }
        return pGuiMemo;
    }
};

然后你的TabsBuilder :: Build()函数可以调用GuiMemoCreator :: CreateMemo()函数来构建你想要绘制的对象。