【发布时间】:2010-10-17 02:19:54
【问题描述】:
我需要用 C++ 实现工厂类,但是当我想到这个时,我发现了一个我无法解决的大问题,我发现周围所有的工厂实现示例都存在缺陷方式。可能是我错了,但请告诉我原因。
所以这里是简单的“典型”工厂实现,它允许我在不更改工厂类的情况下注册新对象。
//fruit.h
class Fruit
{
protected :
int count;
public :
Fruit(int count) : count(count) {}
virtual void show() = 0;
};
// factory.h
/** singleton factory */
class Factory
{
typedef Fruit* (*FruitCreateFunction)(int);
static Factory* factory;
std::map<std::string, FruitCreateFunction> registeredFruits;
public :
static Factory& instance()
{
if (factory == NULL)
factory = new Factory();
return *factory;
}
bool registerFruit(const std::string& name, Fruit* (createFunction)(int))
{
registeredFruits.insert(std::make_pair(name, createFunction));
return true;
}
Fruit* createFruit(const std::string& name, int count)
{
return registeredFruits[name](count);
}
};
//factory.cpp
Factory* Factory::factory = NULL;
//apple.h
class Apple : public Fruit
{
static Fruit* create(int count) { return new Apple(count); }
Apple(int count) : Fruit(count) {}
virtual void show() { printf("%d nice apples\n", count); };
static bool registered;
};
// apple.cpp
bool Apple::registered = Factory::instance().registerFruit("apple", Apple::create);
//banana.h
class Banana : public Fruit
{
static Fruit* create(int count) { return new Banana(count); }
Banana(int count) : Fruit(count) {}
virtual void show() { printf("%d nice bananas\n", count); };
static bool registered;
};
// banana.cpp
bool Banana::registered = Factory::instance().registerFruit("banana", Banana::create);
// main.cpp
int main(void)
{
std::vector<Fruit*> fruits;
fruits.push_back(Factory::instance().createFruit("apple", 10));
fruits.push_back(Factory::instance().createFruit("banana", 7));
fruits.push_back(Factory::instance().createFruit("apple", 6));
for (size_t i = 0; i < fruits.size(); i++)
{
fruits[i]->show();
delete fruits[i];
}
return 0;
}
好的,这段代码看起来很花哨,而且可以运行,但是这里出现了但是:
C++ 标准不允许我定义全局(静态)变量的定义顺序。
我这里有 3 个静态变量
Apple::registered;
Banana::registered;
Factory::factory;
Factory::factory 指针需要在 Apple(或 Banana)::registered 变量之前定义为 NULL,否则 Factory::instance 方法将在未初始化的情况下工作价值,并且行为不可预测。
那么,我没有得到什么?代码真的只是偶然发生的吗?如果是这样,我应该如何解决这个问题?
【问题讨论】:
-
Apple::registered设置的值是否依赖于 Factory::factory? -
这更多是您实现单例而不是工厂的问题。
-
模式之所以被称为模式,是因为它们不是一种实现。说有一个典型的模式是矛盾的,因为模式需要针对特定情况进行定制,因此它是一种模式,不是一种实现。
-
你应该考虑修改你的代码,你正在泄漏你的单例并且没有将分配的
Fruit放在某种智能管理器中,这也会使你面临内存泄漏(在异常情况下)。 -
@Matthieu M Thx,我知道这个版本会泄露,我想让它尽可能简单。其实我在Factory::instance函数中使用局部静态变量作为工厂实例,所以根本没有用到Factory::factory指针。
标签: c++ singleton factory factory-pattern