【Effective Javaを読む】　第２章　項目３　『privateのコンストラクタかenum型でシングルトン特性を強制する』

#privateのコンストラクタかenum型でシングルトン特性を強制する


Java1.5より前ではシングルトンを実装する方法が2つあった（例１、例２）けど、1.5でできるようになった3つ目の方法（例４）が一番良いねってお話。

##用語集

###シングルトン

デザインパターンの一種。
「Singleton（シングルトン）パターン」と呼ばれることもある。
手短に言えば厳密に一度しかインスタンスが作成されないクラス。
「あるクラスのインスタンスが常にたった1つしか存在していない」という状態を実現したいときに利用される。

シングルトンの作り方
・コンストラクタをprivateで宣言する。
　（このクラスを利用する側からコンストラクタを呼び出せないようにするため）

・インスタンスを取得するメソッドgetInstance( )をstaticで宣言する。
　これにより、利用側はSingleton#getInstance( )という呼び出しでインスタンスを取得することができる。

```java:シングルトンサンプル
/**
 * アプリケーション全体の設定情報
 */
public class Config {
    /**
     * 外部からインスタンス化できないよう、コンストラクタをprivateで宣言する
     */
    private Config() {
        // 実際はファイル・データベースなどから設定情報を
        // 読み込む処理をここに書く
    }

    /**
     * 唯一のインスタンスを返す
     * @return このクラスの唯一のインスタンス
     */
    public static Config getInstance() {
        return ConfigInstanceHolder.INSTANCE;
    }

    /**
     * 指定されたキーに対応する設定値を返す
     * @param key 設定キー
     * @return 設定値
     */
    public String getValue(String key) {
        // 実際はコンストラクタで読み込んだ設定情報を
        // 返す処理をここに書く
        return ....;
    }

    /**
     * Configクラスの唯一のインスタンスを保持する内部クラス
     */
    public static class ConfigInstanceHolder {
        /** 唯一のインスタンス */
        private static final Config INSTANCE = new Config();
    }
}

```

###enum型
Enum(列挙型)とは、複数の定数をひとつにまとめておくことができる型のこと。
Enumで定義する定数のことを列挙子と呼ぶ。

```java
public class Main {
 
    public static void main(String[] args) {
        Fruit fruit_type = Fruit.Orange;
        
        System.out.println(fruit_type);
    }
    
    protected enum Fruit {
        Orange,
        Apple,
        Melon
    };
    
}
```

```:実行結果
Orange
```


###Elvis Presley

偉大なるロックンローラー
私は「A Little Less Conversation」が好きです
https://www.youtube.com/watch?v=Zx1_6F-nCaw

###Elvis has left the Building.

往年の人気歌手エルビス・プレスリーの有名なエピソードにまつわる表現です。
プレスリーのコンサートが終わっても、アンコールを期待してなかなか帰ろうとしない聴衆に向かって「エルビスはもうこの建物を出ました」とアナウンスを流して、聴衆が会場から去るよう促したことが始まりです。

現在は、どのようなイベントについても、終了したことについて使われます。


##サンプルコード
###1.5より前でのシングルトンの作り方その１
コンストラクタをpriavteにして、クラスの利用者がそのクラスの唯一のインスタンスにアクセスできるようにpublic staticのメンバを提供している。

privateのコンストラクタは、public static finalのフィールドであるElvis.INSTANCEを初期化するために１度だけ呼ばれる。
これでElvisが世界に一人しかいないことが保証される。

```java:例１

//public finalのフィールドによるシングルトン
public class Elvis{
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }

    public void leaveTheBuliding() { ... }

}

```

###1.5より前でのシングルトンの作り方その２
その１のメンバをpublic staticにするのが2つ目の方法。
Elvis.getInstance()でオブジェクト参照を返す。
この良いところは宣言によりそのクラスがシングルトンになっていることが明白であること。


```java:例２

//staticファクトリーメソッドによるシングルトン
public class Elvis{
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public static Elvis getInstance() { return INSTANCE; }

    public void leaveTheBuilding() { ... }
}

```

でも、例１、例２の方法で作られたElvisには偽物が存在する可能性があって、それを防ぐには以下のようなメソッドを追加する必要がある。

```java:例３

//シングルトン特性を保持するためのreadResolveメソッド
private Object readResolve() throws ObjectStreamException{
    /*
     * 本物のElvisを返して、Elvisの偽物をガーベジコレクタに
     * 始末させる。
     * 
     */
    return INSTANCE;
}

```

###最新の一番良い方法
Java 1.5からできるようになった3つ目の方法。
単一要素をもつenum型を単純に作るだけ。
簡単な記述だし偽物を許さない鉄壁さもあるからシングルトンを作るならこのやり方にしましょう、だって。

```java:例４

// enumシングルトン - 好ましい方法
public enum Elvis {
    INSTANCE;

    public void leaveTheBuilding() { ... }
}

```

#続く

【Effective Javaを読む】　第２章　項目４　『privateのコンストラクタでインスタンス化不可能を強制する』
https://qiita.com/Natsukii/items/661b645482d814b73914