本文へスキップ
BecomeCoder

C#デザインパターンコース · 第1章 デザインパターン · レッスン1

生成①:Factory Method / Abstract Factory

ブラウザで完結

導入

生成に関するパターンは「オブジェクトの作り方」を工夫します。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です。

実際に動かしてみよう

このレッスンのサンプルは、実務と同じように役割ごとの .cs ファイルへ分けてあります。下のエディタは最初からその複数ファイルが入った状態で、上のタブでファイルを切り替えられます。そのまま「▶ 実行」を押せば全ファイルをまとめてコンパイルして動かせるので、クラスを足したりファイルをまたいで書き換えたりしながら進めましょう(演習は本文のコードをコピーして Program.cs のタブに貼り付ければ試せます)。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。

次のレッスンへ →