はじめに
デザインパターンは、オブジェクト指向設計において再利用可能で柔軟なコードを構築するための重要な手法です。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. 簡単ファクトリーパターンとファクトリーメソッドパターンの比較
| 項目 | 簡単ファクトリーパターン | ファクトリーメソッドパターン |
|---|---|---|
| 柔軟性 | 新しい製品を追加するたびにファクトリークラスを修正する必要がある。 | 新しい製品の追加時に既存のコードを変更する必要がない。 |
| 開閉原則への対応 | 違反。既存コードを変更する必要がある。 | 準拠。新しいクラスを追加するだけで対応可能。 |
| 実装の簡易性 | 実装がシンプルで、クラス数が少ない。 | クラス数が増えるが、コードの再利用性が高い。 |
おわりに
簡単ファクトリーパターンは小規模なアプリケーションや変更の少ないケースに適しており、ファクトリーメソッドパターンは柔軟性が求められる大規模なアプリケーションに最適です。プロジェクトの要件に応じて、適切なパターンを選択してください。