Menu
Coddy logo textTech

Factoryパターン

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

Factoryパターンは、オブジェクトの作成を別のmethodまたはclassに委譲する創造パターンです。コード内で直接newを使用する代わりに、factoryにオブジェクトの作成を依頼します。これにより作成ロジックが一元化され、コードの柔軟性が高まります。

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

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

factory は、この意思決定を 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)
    {
        return type switch
        {
            "pdf" => new PdfDocument(),
            "word" => new WordDocument(),
            _ => throw new ArgumentException("Unknown type")
        };
    }
}

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

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // PDFを開く

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

challenge icon

チャレンジ

簡単

Factoryパターンを使用してnotificationシステムを構築しましょう。コード全体で異なるnotificationタイプを直接作成する代わりに、単純な文字列識別子に基づいてどのnotificationを作成するかを判断するFactory classにcreation logicを集約します。

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

  • Notification.csNotifications namespace内に、文字列を返す単一のSend(string message) methodを持つINotification interfaceをDefineします。次に、このinterfaceをImplementする3つのclassを作成します。
    • EmailNotification - "Email: {message}"をreturns
    • SmsNotification - "SMS: {message}"をreturns
    • PushNotification - "Push: {message}"をreturns
  • NotificationFactory.cs:同じnamespace内にNotificationFactory classをCreateし、type stringに基づいてappropriateなINotificationをreturnsするCreate(string type) methodを定義します。
    • "email"EmailNotificationをreturns
    • "sms"SmsNotificationをreturns
    • "push"PushNotificationをreturns
    認識できないtypeの場合は、defaultとしてEmailNotificationをreturnsします。
  • Program.cs:Factory instanceを作成し、それを使用してinputに基づくnotificationを作成することで、すべてをまとめます。Factoryが、どの具体的なclassをinstance化するかに関するすべての判断を処理します。

2つのinputを受け取ります。

  • notification type(例:sms
  • 送信するmessage(例:Your order has shipped

Factoryを使用してappropriateなnotification typeを作成し、そのSend methodをmessageとともにCallして、resultをprintします。

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

Push: Meeting in 5 minutes

main codeではnew EmailNotification()などを一切使用せず、必要なものをFactoryに要求するだけであることに注目してください。後からSlackNotificationを追加する場合も、notificationを作成するすべての場所ではなく、Factoryだけを更新すれば済みます。

自分で試してみよう

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#オンラインコンパイラ