我正在实现一个抽象的工厂模式(在c ++中),但是有一个小问题。
我想避免创建一个在编译时必须知道工厂存在的地方。
通常在示例中我会看到类似的内容。
Factory * getFactory()
{
if(/*we should make factoryA*/)
{
return FactoryA::instance();
}
else if(/*we should return FactoryB*/)
{
return FactoryB::instance();
}
else
{
return NULL;
}
}
我可以做这样的事,但我想要更好!
我想到的是,Factory基类会有一个工厂列表,每个继承自 Factory 的类都会创建一个静态实例,并通过受保护的类将该实例添加到列表中功能在工厂。
但是,如果不使用静态对象初始化播放俄语轮盘,我无法找到一种方法。
答案 0 :(得分:3)
为避免静态初始化顺序出现问题,可以使列表成为函数getFactoryList()的静态成员。这将确保当受保护的构造函数需要将工厂添加到列表时列表存在。
然后,您需要向Factory添加虚拟方法,以确定是否应使用给定的工厂。希望一次只有一家工厂有资格使用,因此工厂创建的订单不会改变返回的工厂。
答案 1 :(得分:1)
简单的事情:
class BaseFactory
{
public:
BaseFactory()
{
std::list<BaseFactory*>& fList = getFactoryList();
fList.push_back(this);
// If you are feeling brave.
// Write the destructor to remove the object from the list.
//
// Note C++ guarantees the list will live longer than any of the factories
// Because the list will always be completely constructed before any
// of the factory objects (because we get the list in the constructor).
}
static BaseFactory& getFactory() // Don't return a pointer (use a reference)
{
std::list<BaseFactory*>& fList = getFactoryList();
std::list<BaseFactory*>::iterator i = selectFactory(fList);
if (i == fList.end()
{
static FakeFactory fakeFactory; // Having a fake factory that
// that returns fake object
// is usually a lot easier than checking for
// NULL factory objects everywhere in the code
//
// Alternatively throw an exception.
return fakeFactory;
}
return *(*i); // return reference
}
private:
static std::list<BaseFactory*>& getFactoryList()
{
static std::list<BaseFactory*> factoryList; // Notice the static
return factoryList;
}
};
答案 2 :(得分:0)
您如何从这样的设计中受益?我的意思是,即使您有该列表,您也必须根据某些标准以某种方式选择该工厂。
尝试使用Inversion Of Control模式。
如果A类需要创建一个对象,请将工厂传递给该类。
class A {
Factory *f;
public:
A(Factory *f)
: f(f)
{ }
void doSomething()
{
Object o = f->produce();
...
}
}
然后您将决定在“更高级别”使用哪个工厂。工厂可能来源,形式插件等。
答案 3 :(得分:0)
我使用模式来收集子类的实例。就工厂而言,这是它的基础:
class Factory {
public:
virtual Foo* makeFoo()=0;
...
protected:
Factory(){
getFactoryList().push_back(this);
}
private:
FactoryList& getFactoryList(); // Returns static list
};
class FactoryA: public Factory{
Foo* makeFoo(); // I make a Foo my way
} FACTORYINSTANCE;
您仍然需要一种在列表中搜索要使用的正确工厂的方法,并且我的宏FACTORYINSTANCE仅评估一个唯一的名称,以便调用自己的构造函数。