導入
生成に関するパターンは「オブジェクトの作り方」を工夫します。Factory Methodは「どのクラスを作るかを1か所に集約」し、Abstract Factoryは「関連する部品一式をまとめて生成」します。newを呼び出し側から隠すのが共通の狙いです。
図解
flowchart TB
C["呼び出し側"] -->|種類を渡すだけ| F["Factory<br/>どの具体クラスを new するか決める"]
F --> P1["Circle"]
F --> P2["Square"]
style F fill:#e1f5fe
サンプル
実務ではクラス1つにつきファイル1つが基本です。下のエディタも同じ構成になっていて、上のタブでファイルを切り替えられます(そのまま「▶ 実行」を押せば全ファイルまとめてコンパイルされます)。
1. 図形の共通の形(IShape.cs)。呼び出し側が知るのはこの形だけです。
public interface IShape
{
void Draw();
}
2. 具体的な図形(Circle.cs / Square.cs)。工場が作る「製品」たち。増えても呼び出し側は影響を受けません。
public class Circle : IShape
{
public void Draw() => Console.WriteLine("○を描く");
}
public class Square : IShape
{
public void Draw() => Console.WriteLine("□を描く");
}
3. 工場(ShapeFactory.cs)。newの分岐がこのファイルだけに集まります。図形を増やすときに触るのはここです。
// Factory Method: 生成の判断を工場メソッドに集約
public static class ShapeFactory
{
public static IShape Create(string kind) => kind switch
{
"circle" => new Circle(),
"square" => new Square(),
_ => throw new ArgumentException("未知の図形"),
};
}
4. 部品一式の工場(IUIFactory.cs / DarkFactory.cs)。Abstract Factoryは「関連する部品をまとめて作る」役です。テーマを増やすときは工場クラスを1つ足すだけで済みます。
public interface IUIFactory
{
string CreateButton();
string CreateCheckbox();
}
// Abstract Factory: 一貫性のある部品群(ダークテーマ一式)をまとめて生成
public class DarkFactory : IUIFactory
{
public string CreateButton() => "[ダークボタン]";
public string CreateCheckbox() => "[ダークチェック]";
}
5. 呼び出し側(Program.cs)。new Circle() とは一度も書いていないことに注目してください。
IShape shape = ShapeFactory.Create("circle");
shape.Draw(); // ○を描く
IUIFactory factory = new DarkFactory();
Console.WriteLine(factory.CreateButton()); // [ダークボタン]
Console.WriteLine(factory.CreateCheckbox()); // [ダークチェック]
- Factory Method:
newの分岐を工場メソッドに集約し、呼び出し側は種類を指定するだけ - Abstract Factory: 一貫性のある部品群(例: ダークテーマ一式)をまとめて作る
- どちらも「具体クラスへの依存」を呼び出し側から切り離す
- ファイルを分けると「増えるのはどこか」(=製品ファイルと工場ファイル)が一目でわかる
演習
IAnimal a = AnimalFactory.Create("dog");
a.Cry(); // ワン
// TODO: "dog"→Dog(Cry→"ワン"), "cat"→Cat(Cry→"ニャー") を生成する
// ShapeFactory 風の AnimalFactory.Create を完成させてください
interface IAnimal { void Cry(); }
class Dog : IAnimal { public void Cry() => Console.WriteLine("ワン"); }
class Cat : IAnimal { public void Cry() => Console.WriteLine("ニャー"); }
___
- 期待される出力:
ワン
ヒント1を見る
static class AnimalFactory { public static IAnimal Create(string k) => k switch { "dog" => new Dog(), "cat" => new Cat(), _ => throw new ArgumentException() }; }
ヒント2を見る
switch式で種類ごとにnewを返します
まとめ
- Factory Methodは生成の判断を1か所に集約する
- Abstract Factoryは関連部品一式をまとめて生成する
- 呼び出し側を具体クラスから切り離す
次回: 複雑な生成を段階的に組み立てるBuilderです。