工場が目的とするのは、実行時にプログラムがコンパイルされたときにデータが利用できない可能性があり、多くの場合のうちvirtual
メソッドを持つ特定のクラスから派生したデータを取得する必要があります。あなたのプログラム。
多様な言語機能を使用すると、さまざまな種類のデータ(共通基本クラスを共有)で作業し、型に適した動作を呼び出すことができます。これを利用するには、異なる派生型のオブジェクトを持つ必要があります。 Comp Sciコースでこれについて学ぶときには、各Derivedタイプのいくつかの作成をハードコードし、基本クラスへのポインタを使って演奏します。複雑な現実世界の問題では、ハードコーディング作成ではなく、データベーステーブル、ファイル、ソケットなど、プログラムの入力から到着したデータから逃れることがよくあります。それぞれの点で正確に何が表示されているかに応じて、適切に型付けされたオブジェクトを作成してそれを表現したいと思うかもしれませんが、おそらく、コンパイル時の既知の型、つまり基本クラスへのポインタを使用して、次に、基底クラスが約束している操作を実行できるだけでなく、派生クラスの実装への動的ディスパッチが必要な場合もありますが、必要に応じて、実際のデータ型が何であるかを正確に判断し、 。
struct Animal
{
Animal(const std::string& name) : name_(name) { }
virtual void eat_from(Supplies&) = 0; // animals must do in their own way...
virtual bool can_jump() { return false; } // some animals might, assume not...
std::string name_;
};
struct Elephant : Animal
{
Elephant(const std::string& name, const std::string& partner)
: Animal(name), partner_(partner)
{ }
std::string partner_;
virtual void eat_from(Supplies&) { supplies.consume(Tofu, 10 * kg); }
void swing_trunk(); // something specific to elephants
};
struct Mule : Animal
{
Mule(const std::string& name, double kgs) : Animal(name), kilograms_(kgs) { }
double kilograms_;
virtual void eat_from(Supplies&) { supplies.consume(Grass, 2 * kg); }
virtual bool can_jump() { return true; }
};
:あなたはこれらを表現するために次のクラス階層構造を持っている
elephant name Tip-Toes partner Mega
mule name Dare-You mane_length 132
:たとえば
は、あなたがそれぞれに異なる種類のデータを収集した方法を示し、次のファイルを、読んで言います
ファクトリメソッドの仕事は、ゾウをミュールと区別して、適切なタイプの新しいオブジェクトを返すことです(これは、単にAnimalではありません)。
Animal* factory(std::istringstream& input)
{
std::string what, name;
if (input >> what && input >> name)
{
if (what == "elephant")
{
std::string partner;
if (input >> partner)
return new Elephant(name, partner);
}
else if (what == "mule")
{
double mane_length;
if (input >> mane_length)
return new Mule(name, mane_length);
}
}
// can only reach here on unparsable input...
throw runtime_error("can't parse input");
}
あなたはその後、動物* Sを保存し、それらの操作を実行できます。
あなたの質問に戻って
std::vector<Animal*> animals;
// we expect 30 animals...
for (int i = 0; i < 30; ++i) animals.push_back(factory(std::cin));
// do things to each animal...
for (int i = 0; i < 30; ++i)
{
Animal* p_unknown = animals[i];
std::cout << p_unknown->name() << '\n';
if (Elephant* p = dynamic_cast<Elephant*>(p_unknown))
p->swing_trunk();
}
:
私は現在、私はクラスを持っており、使用するプロジェクトに取り組んでいますオブジェクトを初期化するコンストラクタですが、失敗して初期化されません。正しく作成されたかどうかを確認するSuccessプロパティがあります。これは、ファクトリクラスを実装するときの良い例ですか?この方法でCreate()メソッドはnullを返すことができ、Successプロパティを取り除くことができます。私は正しいアイデアを持っていますか?
いいえ、まだ1つのタイプしか含まれていないため、工場が便利な状況ではありません。あなたは(OOの意味で)持っているものに固執するだけですが、例外をスローしたり、プログラムを中止したりすることができます。
工場クラスまたは工場の方法ですか? – Bozho