Singleton

Singletonパターンは,生成されるインスタンスが,必ず,一つだけ必要であり,複数生成されては困る場合に用いるパターンである. 複数生成されては困るので,生成するメソッドであるコンストラクタに工夫をすることで,インスタンス化が制限されてインスタンスを唯一の存在にすることができる.

クラス構造


Singletonパターンは,インスタンスを唯一にするために工夫を施した,唯一のインスタンスにするようにするクラスのみで完結するデザインパターンである.

例として,地球上で唯一の存在である太陽を模して説明する. Sunクラスは,太陽を模しているため,インスタンスは唯一の存在であると神は設計した.そのために,生成するときに用いるコンストラクタを公にしないように設定する.

さらに,この唯一のクラスであるので,フィールドとして,自分自身を持つようにする.これにより,クラスそれ自身をインスタンスであるととらえることができる.

プログラム

public class Sun
{
    private static Sun sun =  new Sun();
    private Sun()
    {
        System.out.println("太陽出来上がり");
    }
    public static Sun getSun()
    {
        return sun;
    }
    public void getShine()
    {
        System.out.println("ギラギラ");
    }
}

Sunクラスでは,自分自身のフィールドを静的に持っている.これが,唯一のインスタンスが保持される場所である.このフィールドに結び付けるインスタンスをコンストラクタで生成している.

そのコンストラクタの定義はというと,「private」に設定されていることに注目してほしい.通常,コンストラクタの修飾子として,「public」などを設定するが,いずれの修飾子も,クラスの外部からアクセスできるように設定する.それは,クラスのインスタンスを,他のクラスが生成して,利用するためである.しかし,インスタンスを唯一にするために,Singletonパターンでは,外部からインスタンス化することを許さないのである.これによって,インスタンスが唯一であることが保障されるのである.

しかし,このままでは,外部からインスタンスを利用することができない.そのために,クラス自身が持っている自分のインスタンスを参照するためのメソッドを用意する(getSun()メソッド).

public class Main {
    public static void main(String args[])
    {
        Sun sun = Sun.getSun();
        System.out.println("第1の太陽の光:");
        sun.getShine();
        Sun sun2 =  Sun.getSun();
        System.out.println("第2の太陽の光:");
        sun2.getShine();
        System.out.println("第1の太陽の所在地:" + sun.toString());
        System.out.println("第2の太陽の所在地:" + sun2.toString());
        if(sun == sun2)
        {
            System.out.println("太陽は唯一の存在である");
        }
        else
        {
            System.out.println("太陽は複数存在する!");
        }
    }
}

さらに,Sunクラスを利用するときに,必ずSunクラスのインスタンスが唯一であることを確認するためのMainクラスを示す.ここで注目すべきことは,インスタンス化を明示的に行っていないことである.すなわち,「new」をしているところがない.

実行結果

世界の始まり
太陽出来上がり
第1の太陽の光:ギラギラ
第2の太陽の光;ギラギラ
第1の太陽の所在地:Sun@15db9742
第2の太陽の所在地:Sun@15db9742
太陽は唯一の存在である

このプログラムでは,オブジェクトがインスタンス化されるのか,本当にインスタンスは唯一の存在であるのかを確かめる. Sunクラスのオブジェクトを参照するための変数を2つ用意して,それぞれ,インスタンスを取得する.それぞれのオブジェクトのIDを表示されると,同じであることがわかる.等価であるかを確認すると,同じであることがわかる. さらに,インスタンス化されるタイミングについては,getSunされる前であることがわかる.すなわち,Sunが利用されることが明確になってから,静的なフィールドが用意されて,そのフィールドを用意するときにコンストラクタが呼ばれている様子がわかる.

演習

(1)Singletonクラスの作成

人体を模したクラスを作るとき,心臓が唯一のインスタンスになるように,クラスを設計し,実装せよ.

心臓が唯一のインスタンスになっていることを確認せよ.