Javaの簡単ファクトリーパターンとファクトリー方法パターンの詳細解説と実装例

はじめに

デザインパターンは、オブジェクト指向設計において再利用可能で柔軟なコードを構築するための重要な手法です。Javaで広く使用されるデザインパターンの一つに「簡単ファクトリーパターン」と「ファクトリーメソッドパターン」があります。本ブログでは、これらの2つのパターンを比較し、それぞれの実装例を通じて特徴や使い方を解説します。また、新しい製品を追加する場合の具体的な手順も示します。


1. 簡単ファクトリーパターン

1.1 簡単ファクトリーパターンの概要

簡単ファクトリーパターンは、クラスのインスタンスを作成する責任を1つの「ファクトリークラス」に集中させるデザインパターンです。このパターンでは、クライアントコードが直接インスタンスを生成せず、ファクトリークラスが必要な製品を返します。

1.2 製品Aと製品Bの作成

以下は、製品Aと製品Bを簡単ファクトリーパターンで作成する例です。

// 製品インターフェース
interface Product {
    void display();
}

// 製品Aの具体的実装
class ProductA implements Product {
    public void display() {
        System.out.println("This is Product A");
    }
}

// 製品Bの具体的実装
class ProductB implements Product {
    public void display() {
        System.out.println("This is Product B");
    }
}

// 簡単ファクトリークラス
class SimpleFactory {
    public static Product createProduct(String type) {
        if (type.equals("A")) {
            return new ProductA();
        } else if (type.equals("B")) {
            return new ProductB();
        } else {
            throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// クライアントコード
public class SimpleFactoryDemo {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.display(); // 出力: This is Product A

        Product productB = SimpleFactory.createProduct("B");
        productB.display(); // 出力: This is Product B
    }
}

1.3 製品Cの追加

製品Cを追加する場合、簡単ファクトリークラスを以下のように変更します。

// 製品Cの具体的実装
class ProductC implements Product {
    public void display() {
        System.out.println("This is Product C");
    }
}

// 簡単ファクトリークラスの修正
class SimpleFactory {
    public static Product createProduct(String type) {
        if (type.equals("A")) {
            return new ProductA();
        } else if (type.equals("B")) {
            return new ProductB();
        } else if (type.equals("C")) { // 新しい分岐
            return new ProductC();
        } else {
            throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// クライアントコード
public class SimpleFactoryDemo {
    public static void main(String[] args) {
        Product productC = SimpleFactory.createProduct("C");
        productC.display(); // 出力: This is Product C
    }
}

ポイント: 簡単ファクトリーパターンでは、新しい製品を追加するたびにファクトリークラスを変更する必要があります。これは、「開閉原則」(拡張に対して開かれ、変更に対して閉じているべき) に反します。


2. ファクトリーメソッドパターン

2.1 ファクトリーメソッドパターンの概要

ファクトリーメソッドパターンは、製品の作成を「具体的なファクトリークラス」に委ねるパターンです。この方法では、製品ごとにファクトリークラスを作成する必要がありますが、新しい製品を追加する際に既存コードを変更する必要がありません。これにより、開閉原則に従った設計が可能です。

2.2 製品Aと製品Bの作成

以下は、ファクトリーメソッドパターンを使用して製品Aと製品Bを作成する例です。

// 製品インターフェース
interface Product {
    void display();
}

// 製品Aの具体的実装
class ProductA implements Product {
    public void display() {
        System.out.println("This is Product A");
    }
}

// 製品Bの具体的実装
class ProductB implements Product {
    public void display() {
        System.out.println("This is Product B");
    }
}

// ファクトリーインターフェース
interface Factory {
    Product createProduct();
}

// ファクトリーAの具体的実装
class FactoryA implements Factory {
    public Product createProduct() {
        return new ProductA();
    }
}

// ファクトリーBの具体的実装
class FactoryB implements Factory {
    public Product createProduct() {
        return new ProductB();
    }
}

// クライアントコード
public class FactoryMethodDemo {
    public static void main(String[] args) {
        Factory factoryA = new FactoryA();
        Product productA = factoryA.createProduct();
        productA.display(); // 出力: This is Product A

        Factory factoryB = new FactoryB();
        Product productB = factoryB.createProduct();
        productB.display(); // 出力: This is Product B
    }
}

2.3 製品Cの追加

製品Cを追加する場合、以下のように新しい製品クラスとファクトリークラスを追加します。

// 製品Cの具体的実装
class ProductC implements Product {
    public void display() {
        System.out.println("This is Product C");
    }
}

// ファクトリーCの具体的実装
class FactoryC implements Factory {
    public Product createProduct() {
        return new ProductC();
    }
}

// クライアントコード
public class FactoryMethodDemo {
    public static void main(String[] args) {
        Factory factoryC = new FactoryC();
        Product productC = factoryC.createProduct();
        productC.display(); // 出力: This is Product C
    }
}

ポイント: ファクトリーメソッドパターンでは、既存のコードを一切変更せずに製品を追加できます。これにより、設計の柔軟性が向上します。


3. 簡単ファクトリーパターンとファクトリーメソッドパターンの比較

項目 簡単ファクトリーパターン ファクトリーメソッドパターン
柔軟性 新しい製品を追加するたびにファクトリークラスを修正する必要がある。 新しい製品の追加時に既存のコードを変更する必要がない。
開閉原則への対応 違反。既存コードを変更する必要がある。 準拠。新しいクラスを追加するだけで対応可能。
実装の簡易性 実装がシンプルで、クラス数が少ない。 クラス数が増えるが、コードの再利用性が高い。

おわりに

簡単ファクトリーパターンは小規模なアプリケーションや変更の少ないケースに適しており、ファクトリーメソッドパターンは柔軟性が求められる大規模なアプリケーションに最適です。プロジェクトの要件に応じて、適切なパターンを選択してください。