【GoFのデザインパターン】生成パターン:Factory Methodパターン

当サイトではアフィリエイト広告を利用しています。

GoF

Factory Methodパターンとは

教授:まず、Factory Methodパターンとは何か、それがどうして必要なのかを考えてみましょう。オブジェクトの生成に関するパターンの一つで、オブジェクトの作成をサブクラスに委ねることができます。

生徒:オブジェクトの作成をサブクラスに任せることの利点は何ですか?

教授:良い質問です。その主な理由は「柔軟性」にあります。特定のクラスではなく、インターフェースや抽象クラスを通じてオブジェクトを生成することで、将来的に新しいクラスを追加しても、既存のコードを変更せずに済むのです。

生徒:つまり、システムが拡張しやすくなるということですね。

Factory Methodパターンを使用しない場合の問題点

教授:そうです。では、このパターンを使用しない場合にどのような問題が生じるかを見てみましょう。

生徒:はい、教えてください。

教授:Factory Methodパターンを使用しない場合、オブジェクトの生成がコードのあちこちに散らばりがちです。これにより、新しいオブジェクトの種類を追加するたびに、その生成に関わるコードを複数の場所で変更する必要が出てきます。

生徒:それはメンテナンスが大変そうですね。

教授:正解です。また、オブジェクト生成のロジックがアプリケーション全体に散らばることで、コードの理解が難しくなり、バグの原因にもなります。

生徒:Factory Methodパターンを使うことで、そのような問題を解決できるんですね。

教授:その通りです。オブジェクトの生成を専門のメソッドに委ねることで、コードの重複を避け、拡張性とメンテナンス性を向上させることができます。

教授:今日の内容は理解できましたか?

生徒:はい、Factory Methodパターンの必要性と、使用しない場合の問題点がよくわかりました。ありがとうございます。

Factory Methodパターンの概要

Factory Methodパターンは、オブジェクトの作成をサブクラスに任せるデザインパターンです。この方法により、クライアントコードは特定の実装ではなく、インターフェースや抽象クラスに依存することになり、コードの柔軟性と再利用性が向上します。

Factory MethodパターンのC#によるサンプルコード

以下の例では、製品(Product)としてのインターフェースと、その具体的な実装、そして製品を生成するための抽象クリエーター(Factory)とその具体的な実装を示します。

// 製品のインターフェース
public interface IProduct
{
    string Operation();
}

// 具体的な製品A
public class ConcreteProductA : IProduct
{
    public string Operation()
    {
        return "Result of ConcreteProductA";
    }
}

// 具体的な製品B
public class ConcreteProductB : IProduct
{
    public string Operation()
    {
        return "Result of ConcreteProductB";
    }
}

// クリエーター(Factory)の抽象クラス
public abstract class Creator
{
    public abstract IProduct FactoryMethod();

    public string SomeOperation()
    {
        // FactoryMethodを呼び出して、製品のオブジェクトを作成
        var product = FactoryMethod();
        // 製品のオペレーションを使用
        var result = "Creator: The same creator's code has just worked with " + product.Operation();
        return result;
    }
}

// 具体的なクリエーターA
public class ConcreteCreatorA : Creator
{
    public override IProduct FactoryMethod()
    {
        return new ConcreteProductA();
    }
}

// 具体的なクリエーターB
public class ConcreteCreatorB : Creator
{
    public override IProduct FactoryMethod()
    {
        return new ConcreteProductB();
    }
}
        

このサンプルコードでは、Factory Methodパターンを使って異なるタイプの製品オブジェクトを生成しています。クリエータークラスは製品のインスタンス化の詳細を隠蔽し、製品のインターフェースのみをクライアントに公開します。

Factory Methodパターンが解決する問題

教授:さて、Factory Methodパターンを適用することで、私たちはどのような問題を解決できるのでしょうか?

生徒:はい、それがいまいちピンときていません。

教授:まず、オブジェクト生成時の柔軟性の欠如を考えてみましょう。具体的なクラスを直接インスタンス化すると、そのクラスに強く依存することになり、後で変更が難しくなります。

生徒:なるほど、柔軟性がないと、将来的に変更が必要になった時に大変なんですね。

教授:正解です。Factory Methodパターンでは、オブジェクトの生成をサブクラスに委ねることで、この問題を解決します。これにより、新しいクラスを追加したり、生成するオブジェクトの種類を変更したりする場合に、既存のコードに手を加えることなく対応できます。

生徒:他にはどのような問題が解決されるんですか?

教授:もう一つは、オブジェクト生成のロジックがアプリケーションのあちこちに散らばってしまう問題です。これは、メンテナンス性を著しく下げる原因となります。

生徒:それも、Factory Methodを使うことで解決できるんですね。

教授:その通りです。オブジェクトの生成を一箇所に集中させることで、コードが読みやすくなり、メンテナンスや拡張がしやすくなります。さらに、テストのしやすさも向上します。

生徒:Factory Methodパターンを理解することで、より良い設計ができるようになりそうですね。

教授:確かにそうです。デザインパターンを適切に使いこなすことは、プログラミングスキルを次のレベルに引き上げる鍵です。