Factory Methodパターンは、GoF(Gang of Four)によって定義されたデザインパターンの一つで、オブジェクトの生成をサブクラスに委譲する設計手法です。このパターンは、クラスの再利用性を高め、アプリケーションに特化したオブジェクト生成を柔軟に行うことを目的としています。
Factory Methodパターンの概要
Factory Methodパターンでは、親クラス(Creator)がオブジェクトを生成する際に、自身のメソッド(factoryMethod)を呼び出します。このfactoryMethodは、サブクラス(ConcreteCreator)でオーバーライドされることを前提としており、具体的なオブジェクトの生成をサブクラスに委ねます。これにより、親クラスは具体的なオブジェクトの型に依存することなく、オブジェクト生成処理を抽象化することができます。
Factory Methodパターンの
クラス図は以下のようになります。
mermaid
classDiagram
class Creator{
+anOperation()
#factoryMethod()
}
class ConcreteCreator{
+factoryMethod()
}
class Product
class ConcreteProduct
Creator <|-- ConcreteCreator: implements
Creator --|> Product: creates
Product <|-- ConcreteProduct: implements
ConcreteCreator --|> ConcreteProduct: creates
`Creator`: オブジェクトを生成するメソッド`factoryMethod`を持つ抽象クラス。`anOperation`メソッドから`factoryMethod`を呼び出し、`Product`型のオブジェクトを生成・利用します。
`ConcreteCreator`: `Creator`クラスのサブクラスで、`factoryMethod`をオーバーライドして具体的な`Product`型のオブジェクトを生成します。
`Product`: 生成されるオブジェクトのインターフェースまたは抽象クラス。
`ConcreteProduct`: `Product`のサブクラスで、具体的なオブジェクトの型を表します。
`anOperation`メソッドは、`factoryMethod`を呼び出して`Product`のサブクラスのインスタンスを取得し、利用します。`factoryMethod`は、デフォルトの動作を持つ具象メソッドである場合や、パラメータによって生成するクラスを切り替える場合があります。`factoryMethod`はサブクラスでのオーバーライドを前提としているため、privateにはしません。
利用例
Javaでの具体的な利用例として、リストの要素をさまざまな順序で表示するプログラムを考えます。
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
abstract class ListPrinter {
public void printList(List
list) {
Comparator comparator = createComparator();
list.sort(comparator);
for (String item : list) {
System.out.println(item);
}
}
abstract Comparator createComparator();
}
class AscendingOrderPrinter extends ListPrinter {
@Override
Comparator createComparator() {
return String::compareTo;
}
}
class LengthOrderPrinter extends ListPrinter {
@Override
Comparator createComparator() {
return Comparator.comparingInt(String::length);
}
}
public class Main {
public static void main(String[] args) {
List list = new ArrayList<>(Arrays.asList("いちご", "いちじく", "もも"));
System.out.println("五十音順で表示:");
ListPrinter ascendingPrinter = new AscendingOrderPrinter();
ascendingPrinter.printList(list);
System.out.println("
長さ順で表示:");
ListPrinter lengthPrinter = new LengthOrderPrinter();
lengthPrinter.printList(list);
}
}
この例では、`ListPrinter`クラスが抽象クラスで、`printList`メソッド内でソートに使う`Comparator`を生成する`createComparator`メソッドを抽象メソッドとして定義しています。`AscendingOrderPrinter`クラスと`LengthOrderPrinter`クラスは`ListPrinter`クラスのサブクラスで、それぞれ五十音順と長さ順にソートするための`Comparator`を生成します。
`printList`メソッドでは、`new`演算子を使って直接`Comparator`を生成するのではなく、`createComparator`メソッドを通じてサブクラスに`Comparator`の生成を委ねます。これにより、`printList`メソッドは具体的なソート処理に依存せずに、多様なソート処理に対応できます。
関係するパターン
Factory Methodパターンは、Template Methodパターンと組み合わせて使用されることがよくあります。Template Methodパターンで定義されたアルゴリズムの中で、オブジェクトの生成が必要な場合にFactory Methodパターンが利用されます。また、Abstract Factoryパターンでは、Abstract FactoryクラスがFactory Methodを持ち、サブクラスがProductをオーバーライドする手法が一般的です。
Abstract Factoryパターンとの違い
Factory Methodパターンは「クラスパターン」に分類され、Abstract Factoryパターンは「オブジェクトパターン」に分類されます。Factory Methodパターンでは、親クラスである`Creator`クラスが、オブジェクト生成を子クラスである`ConcreteCreator`クラスに委ねるという、クラス同士の関連に焦点を当てます。一方、Abstract Factoryパターンでは、`Client`インスタンスが`ConcreteFactory`のインスタンスにオブジェクトの生成を委ねるという、オブジェクト同士の関連に焦点を当てます。
まとめ
Factory Methodパターンは、オブジェクトの生成をサブクラスに委譲することで、柔軟で再利用性の高いコードを実現する強力なデザインパターンです。このパターンを理解し、適切に活用することで、より保守しやすく拡張性の高いアプリケーションを開発することができます。
関連項目
Template Method パターン
Abstract Factory パターン
デザインパターン
参考文献
『オブジェクト指向における再利用のためのデザインパターン』