大家好!
我正在编写一个小应用程序来保存不同的注释(备忘录),并且有一个我不喜欢的类结构。我在核心中有一个 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
答案 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()函数来构建你想要绘制的对象。