Mar*_*ark 6 c++ oop design-patterns
这与我的其他问题类似,但我认为不同的是保证一个新问题.
基本上我正在编写用户界面,我的用户界面有可以选择的节点.当选择节点时,用户界面以抽象节点基类"INode"结束.从这个我做节点 - > getFactory(),并从这个我可以创造此时,相应的对话框或观看该节点,因为正确的工厂得到由混凝土节点返回(如出厂> createAddDialog(),出厂时得到一个工厂> createView(节点)等).
我的问题是,试图找到该工厂进入摆在首位的节点的最佳途径.
到目前为止,我已经想到了3种方法:
1)创建节点时注入正确的工厂:
AreaNode *node = new AreaNode(new AreaNodeFactory());
Run Code Online (Sandbox Code Playgroud)
所以AreaNode的定义是:
AreaNode : public INode
{
AreaNode(INodeAbstractFactory *injectedFactory)
{
m_injectedFactory = injectedFactory;
}
INodeAbstractFactory* getFactory()
{
return m_injectedFactory;
}
INodeAbstractFactory* m_injectedFactory;
};
Run Code Online (Sandbox Code Playgroud)
2)注入一个更通用的工厂并允许节点从该工厂获得工厂:
AreaNode : public INode
{
AreaNode(IFactory *injectedFactory)
{
m_injectedFactory = injectedFactory;
}
INodeAbstractFactory* getFactory()
{
return m_injectedFactory->getAreaNodeFactory();
}
IFactory* m_injectedFactory;
}
Run Code Online (Sandbox Code Playgroud)
3)只需创建具体工厂(尽管这样就删除了为同一节点使用不同工厂的范围,可能用于测试或以后的更改):
AreaNode : public INode
{
INodeAbstractFactory* getFactory()
{
return new AreaNodeFactory();
}
}
Run Code Online (Sandbox Code Playgroud)
目前关于这些选择的想法:
选项1:可能是有点杂乱无章 - 我必须确保我总是给它正确的工厂为该类型,也许我可以只使用另一家工厂注入正确的工厂给我.
选项2:强制了解抽象工厂实现足以能够调用getAreaNodeFactory,这可能不是一件坏事节点.它至少有助于确保始终获取正确/相同的工厂(假设更一般的工厂正确实施).
方案3:这种感觉,因为我不能够交换类出一点限制,我并不热衷于为了解具体执行工厂的节点 - 尽管在这种情况下,它可能不会太大一个问题(着名的遗言!).
有什么想法吗?
谢谢.
编辑:抱歉错过了原始帖子中的变量声明,更正了.
编辑:选项2的另一个问题是我必须在每个节点类型中实现"getFactory".至少对于选项1,基类每次都可以返回注入抽象工厂类.
怎么样
class FactoryBase { /* interface */ }
template <typename NodeType> class Factory : public FactoryBase {
// Default implementation.
}
// Add appropriate specializations for all relevant nodetypes, if needed.
template <typename NodeType> inline Factory<NodeType> getFactory(NodeType*) {
return Factory<NodeType>( );
}
class AreaNode : public Node {
FactoryBase getFactory() { return getFactory(this); }
};
Run Code Online (Sandbox Code Playgroud)
模板参数推导将确保工厂类型派生自this. 这应该可以防止出现手动错误。但总的来说,我根本不会费心去公开曝光一家工厂。只需将以下位添加到基类中:
class Node {
public:
std::Auto_ptr<View> createView( ) {
this->getFactory()->createView(this);
} // etc.
private:
virtual FactoryBase* getFactory() = 0;
};
Run Code Online (Sandbox Code Playgroud)