Factory Method パターン

Factory Method パターン（ファクトリメソッド・パターン）とは、GoF (Gang of Four; 四人組)によって定義されたデザインパターンの1つである。 Factory Method パターンは、他のクラスのコンストラクタをサブクラスで上書き可能な自分のメソッドに置き換えることで、 アプリケーションに特化したオブジェクトの生成をサブクラスに追い出し、クラスの再利用性を高めることを目的とする。
Virtual Constructor パターンとも呼ばれる。

クラス図

Factory Method パターンのクラス図は以下の通りである。
ここで、anOperationはfactoryMethodを呼び出し、Productのサブクラスのインスタンスを得て、利用する。factoryMethodのようなメソッドはfactory methodと呼ばれる。
factoryMethodは、デフォルトの動作を含んだ具象メソッドである場合もある。パラメータを取り、それによって生成するクラスを変えることもある。ConcreteCreatorごとの操作手段を Productとして他のクラスに提供するようなケースでは、factoryMethodをpublicとして公開する。。しかし、factoryMethodは上書きされることが前提であるため、privateにはしない。

利用例

例として、Java でリストの要素をさまざまな順で表示するプログラムを考える。このソースコードは J2SE 1.5 以降のバージョンで動作する。
import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;
 
// Creatorに相当するabstract class ListPrinter {
    // anOperationに相当する
    public void printList(List<String> list) {
        Comparator<String> comparator = createComparator();
        list = new ArrayList<String>(list);
 
        Collections.sort(list, comparator);
 
        for (String item : list) {
            System.out.println(item);
        }
    }
 
    // factoryMethodに相当する
    protected abstract Comparator<String> createComparator();}
 
// ConcreteCreatorに相当するclass DictionaryOrderListPrinter extends ListPrinter {
    @Override
    protected Comparator<String> createComparator() {
        return new DictionaryOrderComparator();
    }}
 
// java.util.ComparatorがProductに相当する
 
// ConcreteProductに相当するclass DictionaryOrderComparator implements Comparator<String> {
    @Override
    public int compare(String str1, String str2) {
        return str1.compareTo(str2);
    }}
 
// ConcreteCreatorに相当するclass LengthOrderListPrinter extends ListPrinter {
    @Override
    protected Comparator<String> createComparator() {
        return new LengthOrderComparator();
    }}
 
// ConcreteProductに相当するclass LengthOrderComparator implements Comparator<String> {
    public int compare(String str1, String str2) {
        return str1.length() - str2.length();
    }}
 
// メインクラスpublic class FactoryMethodSample {
    public static void main(String args[]) {
        List<String> list = Arrays.asList("いちご", "もも", "いちじく");
 
        System.out.println("五十音順で表示:");
        new DictionaryOrderListPrinter().printList(list);
 
        System.out.println();
 
        System.out.println("長さ順で表示:");
        new LengthOrderListPrinter().printList(list);
    }}
このプログラムは、以下の結果を出力する。

五十音順で表示:
いちご
いちじく
もも

長さ順で表示:
もも
いちご
いちじく
前半ではリストを五十音順で表示し、後半ではリストを文字列の長さ順に表示している。 リストを並び変えて表示するListPrinter#printListメソッドでは、並び変えに使うComparatorを生成する際にnew演算子を使って直接生成するのではなく、抽象メソッドcreateComparatorを使ってサブクラスに生成を委ねる。

関係するパターン

factory methodは普通template method (Template Method パターンを参照)であるanOperationから呼ばれる。ただし、factory methodをpublicにして他のクラスからも呼ぶ場合もある。
Abstract Factory パターンのAbstractFactoryクラスはfactory methodを持ち、それを個々のサブクラスが上書きして生成するProductを変える手法が一般的である。しかし、Prototype パターンを使い、prototypeとなるオブジェクトの変更により生成するProductを変える手法もある。

Abstract Factory パターンとの違い

『オブジェクト指向における再利用のためのデザインパターン』においてはFactory Method パターンは「クラスパターン」に分類されている。一方Abstract Factory パターンは「オブジェクトパターン」に分類されている。
Factory Method パターンは親クラスであるCreatorクラスが子クラスであるConcreteCreatorクラスにオブジェクトの生成を委ねるという、CreatorクラスとConcreteCreatorクラスとの関連である。一方でAbstract Factory パターンは、ClientのインスタンスがConcreteFactoryのインスタンスにオブジェクトの生成を委ねるという、オブジェクト同士の関連である。