拡張性/柔軟性を獲得する章

3.2. 怠惰な初期化

『目的』

インスタンス生成のタイミングを遅らせる方法を知っておきましょう。

『Before』

初期化は通常コンストラクタを呼び出したときに行います。

このクラスは、ごくまれにしか呼ばれないメソッドしか持っていないのに、 コンストラクタ時に重たいインスタンスを生成しています。

public class Hoge {

    /** とても重いクラス。 */
    private Heavy heavy = new Heavy();
    
    /* まれにしか呼ばれないメソッドその1。 */
    private void method1() {
        heavy.foo();
    }

    /* まれにしか呼ばれないメソッドその2。 */
    private void method2() {
        heavy.bar();
    }
}

この重たいインスタンスが一度も使われなかったら生成するための時間とメモリが無駄になってしまいますよね。 使われるまで生成しないようにすべきでしょう。

『After』

そこで、怠惰な初期化(LazyInit)という考え方を導入します。

public class Hoge {

    /** とても重いクラス。 */
    private Heavy heavy;
    
    /* まれにしか呼ばれないメソッドその1。 */
    private void method1() {
        getHeavy().foo(); // getHeavy経由で heavy 取得
    }

    /* まれにしか呼ばれないメソッドその2。 */
    private void method2() {
        getHeavy().bar(); // getHeavy経由で heavy 取得
    }

    /* Heavy を作るファクトリメソッド。
     * 既に作られていたら、存在するインスタンスを返却。
     */
    private Heavy getHeavy() {
        if (heavy == null) {
            heavy = new Heavy();
        }
        return heavy;
    }
}

こうすれば、使いたくなったときに初めてインスタンスが生成されますね。

『まとめ』

LazyInitによって生成タイミングを遅らせることができます。
レスポンスの向上が期待できたり、無駄なメモリ確保を防いだりできます。

< 前のページへ

Pagetop