Menu
CoddyTech

Factoryパターン

CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 53/70。

Factory パターンは、オブジェクトの生成を個別のメソッドまたはクラスに委譲する生成パターンです。コード内で直接 new を使用する代わりに、ファクトリにオブジェクトの生成を依頼します。これにより生成ロジックが一元化され、コードの柔軟性が高まります。

さまざまな種類のドキュメントを作成する必要がある状況を考えてみましょう。ファクトリーがないと、コードは特定のクラスに強く結合してしまいます。

// Factoryなし - 散在した作成ロジック
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

ファクトリーは、この意思決定を1か所にカプセル化します。

public interface IDocument
{
    void Open();
}
public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}
public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}
public class DocumentFactory
{
    public IDocument Create(string type)
    {
        switch (type)
        {
            case "pdf":
                return new PdfDocument();
            case "word":
                return new WordDocument();
            default:
                throw new ArgumentException("Unknown type");
        }
    }
}

これでクライアントコードは、具象クラスを知らなくても必要なものを簡単に要求できます。

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // PDFを開いています

Factoryパターンは、後から新しい型を追加する必要があるときに真価を発揮します。SpreadsheetDocumentを追加する場合、変更が必要なのはファクトリだけであり、ドキュメントが作成されるすべての場所ではありません。この分離により、コードベースの保守とテストが容易になります。

challenge icon

チャレンジ

簡単

Factoryパターンを使用して通知システムを構築しましょう。コード全体で異なる通知タイプを直接作成する代わりに、作成ロジックをファクトリクラスに集約し、単純な文字列識別子に基づいて作成する通知を決定します。

コードを3つのファイルに分けて整理します。

  • Notification.cs:Notifications名前空間に、文字列を返す単一のメソッドSend(string message)を持つINotificationインターフェースを定義します。次に、このインターフェースを実装する3つのクラスを作成します。
    • EmailNotification - "Email: {message}"を返します
    • SmsNotification - "SMS: {message}"を返します
    • PushNotification - "Push: {message}"を返します
  • NotificationFactory.cs:同じ名前空間にNotificationFactoryクラスを作成し、タイプ文字列に基づいて適切なINotificationを返すCreate(string type)メソッドを実装します。
    • "email"はEmailNotificationを返します
    • "sms"はSmsNotificationを返します
    • "push"はPushNotificationを返します
    認識されないタイプの場合は、デフォルトとしてEmailNotificationを返します。
  • Program.cs:ファクトリのインスタンスを作成し、それを使用して入力に基づく通知を作成することで、すべてをまとめます。どの具象クラスをインスタンス化するかに関する判断は、ファクトリがすべて処理します。

2つの入力を受け取ります。

  • 通知タイプ(例:sms)
  • 送信するメッセージ(例:Your order has shipped)

ファクトリを使用して適切な通知タイプを作成し、そのSendメソッドをメッセージとともに呼び出して、結果を出力します。

たとえば、入力がpushとMeeting in 5 minutesの場合、出力は次のようになります。

Push: Meeting in 5 minutes

メインコードではnew EmailNotification()などを決して使用せず、必要なものをファクトリに要求しているだけであることに注目してください。後でSlackNotificationを追加する場合も、通知を作成するすべての箇所ではなく、ファクトリだけを更新すれば済みます。

自分で試してみよう

using System;
using Notifications;

class Program
{
    public static void Main(string[] args)
    {
        // 入力を読み取る
        string type = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: NotificationFactory のインスタンスを作成する

        // TODO: ファクトリを使用して適切な通知を作成する

        // TODO: Send メソッドを呼び出して結果を出力する
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C#オンラインコンパイラ