C++ でファクトリ クラスを実装する必要があるのですが、それについて考えていたときに、解決できない大きな問題が 1 つ見つかり、周りのファクトリ実装の例はすべて同じように欠陥があることがわかりました。私が悪いのかもしれませんが、理由を教えてください。
したがって、ここに単純な「典型的な」ファクトリ実装があります。これにより、Factory クラスを変更せずに新しいオブジェクトを登録できます。
//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;
ポインターは、Apple(または Banana)::registered 変数の前Factory::factory
に NULL に定義する必要があります。そうしないと、メソッドが初期化されていない値で動作し、予期しない動作をします。Factory::instance
それで、私はここに来ていないのですか?コードは偶然だけで本当に動いているのでしょうか? もしそうなら、どうすれば問題を解決できますか?