Javaのstaticファクトリーメソッドについて

Effective Javaを読んでいたところ、とても重要そうなテクニックを見つけたのでメモしておく。

staticファクトリーメソッドとは

staticファクトリーメソッドとは、オブジェクトを返す単なるstaticのメソッドである。
通常、クラスのインスタンスはコンストラクタが提供するが、代わりにstaticなメソッドでオブジェクトを提供する方法もある。無意識にコンストラクタでインスタンスの提供を行わないように注意したい。
staticファクトリーメソッドは、デザインパターンのファクトリーメソッド(Factory Method)ではない点に注意。

staticファクトリーメソッドの例

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

staticファクトリーメソッドの長所

  • コンストラクタと異なり、名前を持つため、コンストラクタに対するパラメータ自身が返されるオブジェクトを表現していない場合には、適切な名前を持つstaticファクトリーメソッドは使いやすく、その結果としてクライアントのコードは読みやすくなる。

  • コンストラクタと異なり、メソッドが呼び出されるごとに新たなオブジェクトを生成する必要がないので、あらかじめ生成しておいたインスタンスを使用したり、オブジェクトが生成された時にインスタンスをキャッシュして、そのインスタンスを繰り返し使用することで、不必要に重複したインスタンスの生成を回避できる。

  • コンストラクタと異なり、メソッドの戻り値型の任意のサブタイプのオブジェクトでも返すことが出来る。例えば、返すオブジェクトのクラスをpublicにすることなく、APIがオブジェクトを返すことが出来る。このような方法により、実装クラスを隠蔽することで、大変簡潔なAPIとなる。

  • パラメータ化された型のインスタンス生成の面倒さを低減することが出来る。文脈から明らかであるにも関わらず、パラメータ化されたクラスのコンストラクタを呼び出す場合には、あいにく型パラメータを指定しなければならない。

以下の冗長な指定方法は型パラメータの長さと複雑さが増すに従って、すぐに苦痛になる。

Map<String, List<String>> m = new HashMap<String, List<String>>();

以下のstaticファクトリーメソッドでは、コンパイラが型パラメータを見つけてくれる。これは、型推定と呼ばれる。

public static <K, V> HashMap<K, V> newInstance() {
    return new HashMap<K, V>();
}
Map<String, List<String>> m = HashMap.newInstance();

staticファクトリーメソッドの短所

  • public、もしくはprotectedで宣言されたコンストラクタを持たないクラスのサブクラスは作れない。
  • staticファクトリーメソッドが他のstaticメソッドと区別がつかない。staticファクトリーメソッドは、コンストラクタのようにはAPIドキュメンテーション内で目立たないため、コンストラクタの代わりにstaticファクトリーメソッドを提供しているクラスのインスタンス化の方法をクラスのドキュメンテーションから知ることが困難になる。

よくあるstaticファクトリーメソッド

よくあるstaticファクトリーメソッドの名前と役割は以下のようになっている。

名前役割
valueOfパラメータと同じ値を持つインスタンスを返す。実質的に型変換メソッドである。
ofvalueOfの代替。より簡潔にしたもの。
getInstanceパラメータで指定されたインスタンスを返すが、同じ値を持つとは言えない。シングルトンの場合には、getInstanceは何も引数を取らず、その唯一のインスタンスが返される。
newInstancegetInstanceに似ているが、newInstanceは返される個々のインスタンスは、すべて別々のインスタンスである点が異なる。
getTypegetInstanceに似ているが、ファクトリーメソッドが対象のクラスと異なるクラスにある場合に使用され。Typeはファクトリーメソッドから返されるオブジェクトの型を示す。
newTypenewInstanceに似ているが、ファクトリーメソッドが対象のクラスと異なるクラスにある場合に使用される。Typeはファクトリーメソッドから返されるオブジェクトの型を示す。

参考
書籍 Effective Java
staticファクトリーメソッド – はっきりいうと、このBlogのテーマはありふれたテーマ―― 「プログラミング」です。