这与我的其他问题之一类似,但我认为有足够的不同来提出一个新问题。
基本上我在写一个用户界面,我的用户界面有可以选择的节点。选择节点时,用户界面以抽象节点基类“INode”结束。由此我通过执行 node->getFactory() 获得了一个工厂,并且由此我可以为该节点创建适当的对话框或 View ,因为具体节点返回了正确的工厂(例如 factory->createAddDialog(),factory->createView(节点等)。
我的问题是首先尝试为该工厂找到进入节点的最佳方式。
到目前为止我想到了3种方式:
1) 创建节点时注入(inject)正确的工厂:
AreaNode *node = new AreaNode(new AreaNodeFactory());
所以AreaNode的定义是:
AreaNode : public INode
{
AreaNode(INodeAbstractFactory *injectedFactory)
{
m_injectedFactory = injectedFactory;
}
INodeAbstractFactory* getFactory()
{
return m_injectedFactory;
}
INodeAbstractFactory* m_injectedFactory;
};
2) 注入(inject)一个更通用的工厂,并允许节点从该工厂获取工厂:
AreaNode : public INode
{
AreaNode(IFactory *injectedFactory)
{
m_injectedFactory = injectedFactory;
}
INodeAbstractFactory* getFactory()
{
return m_injectedFactory->getAreaNodeFactory();
}
IFactory* m_injectedFactory;
}
3) 只需创建具体的工厂(尽管这消除了为同一节点使用不同工厂的范围,可能是为了测试或以后的更改):
AreaNode : public INode
{
INodeAbstractFactory* getFactory()
{
return new AreaNodeFactory();
}
}
目前对这些选项的想法:
选项 1:可能有点随意 - 我必须确保始终为该类型提供正确的工厂,或者我可以使用另一个工厂为我注入(inject)正确的工厂。
选项 2:强制节点充分了解抽象工厂实现,以便能够调用 getAreaNodeFactory,这可能不是一件坏事。它至少有助于确保始终获取正确/相同的工厂(假设更通用的工厂已正确实现)。
选项 3:这感觉没什么限制,因为我无法将类换出,而且我不希望节点必须了解工厂的具体实现 - 尽管在这种情况下它可能不会问题太大了(著名的遗言!)。
对此有什么想法吗?
谢谢。
编辑: 抱歉遗漏了原帖中的变量声明,已更正。
编辑: 选项 2 的另一个问题是我必须在每个节点类型中实现“getFactory”。至少对于选项 1,基类每次都可以只返回注入(inject)抽象工厂类。
最佳答案
怎么样
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); }
};
模板参数推导将确保工厂类型派生自this
。这应该可以防止那里的手动错误。但总的来说,我根本不会为公开曝光一家工厂而烦恼。只需将以下位添加到基类:
class Node {
public:
std::Auto_ptr<View> createView( ) {
this->getFactory()->createView(this);
} // etc.
private:
virtual FactoryBase* getFactory() = 0;
};
关于c++ - 关于抽象工厂和注入(inject)的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3397002/