Effective Java - Item 1. コンストラクタの代わりにファクトリメソッドを検討する

staticなファクトリメソッドを提供し、constructorの代わりに使用することで、インスタンス生成に関するコードをより分かりやすくできる。

staticファクトリメソッドの利点

コンストラクタとは異なり、分かりやすいメソッド名を指定できる。

Ramdom rand = new Random();
BigInteger.probablePrime(500, rand);

上のBigInteger.probablePrimeメソッドは、素数である可能性のある数を返すファクトリメソッドである。new BigInteger(...)というコンストラクタを呼び出すよりも、どのようなBigIntegerインスタンスを生成するのかが明確に表現される。

型変換用のファクトリメソッドなどでは、慣例としてvalueOfofのようなメソッド名が使用される。

Boolean b = Boolean.valueOf(true);

コンストラクタとは異なり、メソッドを呼び出すたびに新しいインスタンスを作成する必要がない。

Service service = Service.getInstance();

上のService.getInstance()は、新しいインスタンスを生成するように実装することも、効率化のために再利用可能なオブジェクトを返すように実装することもできる。シングルトンクラスでは、効率化のためではなく、同じインスタンスを返すためにこの形式のファクトリメソッドを用意する。

コンストラクタとは異なり、戻り値となるオブジェクトを任意の具象クラスのオブジェクトにできる。

オブジェクト指向の多態性を活用した設計を行うには、インターフェースによるメソッドアクセスが必要である。ファクトリメソッドによって実装クラスのインスタンス化を隠せるため、呼び出し側では自然にインターフェースを使ったコーディングができるようになる。

public static Service createService(ServiceType type) {
    switch (type) {
        case FOO:
            return new FooService()
        case BAR:
            return new BarService();
        default:
            return new DefaultService();
    }
}

staticファクトリメソッドの欠点

他のstaticメソッドと区別しにくい。

staticファクトリメソッドは通常のstaticメソッド、つまりクラスメソッドと同じ場所にあるため、constructorに比べてインスタンス化の方法を把握しにくい。クラスのJavadocコメントとして、インスタンス化の方法を明示しておく必要がある。