Design Pattern | Singleton Pattern(シングルトンパターン)

Singletonパターンとは?

  • Singleton(シングルトン)とは、1つの要素だけを持つ集合という意味である。
  • Singletonパターンは、インスタンスが1つだけ存在することを保証する方式である。
  • Singletonパターンは、プログラム内でインスタンスを一度だけ生成したいときに使われる。
  • グローバル変数を使わずにオブジェクトを1つだけ生成し、生成されたオブジェクトをどこからでも参照できるようにするパターンである。
  • プログラム全体で使われる設定情報値も、Singletonパターンを使って1つだけ生成し、情報を共有するために必要である。
  • 例えば、システム設定を表すクラス、ウィンドウシステムを表すクラスなどが挙げられる。
  • GoFデザインパターンでは、生成に関するデザインパターンに分類される。

Singletonパターンのサンプルプログラム

シングルトンインスタンスを生成するプログラムである。

Class Diagram
Singleton Pattern Class Diagram

1. Singletonクラス

唯一のインスタンスを返すクラスである。
Singletonクラスのコンストラクタはprivateに指定する。これはSingletonクラスの外からコンストラクタを呼び出せないようにするためである。

Singleton.java

package com.devkuma.designpattern.creational.singleton.ex1;

public class Singleton {

    private static Singleton singleton = new Singleton();

    private Singleton() {
        System.out.println("인스턴스를 생성하였습니다.");
    }

    public static Singleton getInstance() {
        return singleton;
    }
}

2. Mainクラス

メイン処理を実行するクラスである。

Main.java

package com.devkuma.designpattern.creational.singleton.ex1;

public class Main {
    public static void main(String[] args) {
        Singleton obj1 = Singleton.getInstance();
        Singleton obj2 = Singleton.getInstance();
        if (obj1 == obj2) {
            System.out.println("obj1와 obj2는 동일한 인스턴스입니다.");
        } else {
            System.out.println("obj1와 obj2는 동일한 인스턴스가 아닙니다.");
        }
    }
}

3. 実行結果

인스턴스를 생성하였습니다.
obj1와 obj2는 동일한 인스턴스입니다.

Singletonパターンのメリット

Singletonパターンはインスタンス数に制限を設けている。
インスタンスが複数存在すると、インスタンス同士が互いに影響し、予期しないバグを作る可能性がある。
しかし、インスタンスが1つだけである保証があれば、その前提条件でプログラミングできる。

synchronizedを使用したSingletonパターン

synchronizedを使用したSingletonパターンのプログラム例

複数のオブジェクトから同時にアクセスできるため、synchronizedを宣言すればスレッドセーフになる。

package com.devkuma.designpattern.creational.singleton.ex2;

public class SynchronizedSingleton1 {

    private static Singleton1 instance;

    /**
     * アクセスできないコンストラクタ
     */
    private SynchronizedSingleton1() {
    }

    public static synchronized Singleton1 getInstance() {
        if (instance == null) {
            instance = new Singleton1();
        }
        return instance;
    }

    public static void main(String[] args) {

        Singleton1 singleton1 = Singleton1.getInstance();
        Singleton1 singleton2 = Singleton1.getInstance();

        System.out.println(singleton1);
        System.out.println(singleton2);
    }
}

synchronizedの性能を改善したSingletonパターンのプログラム例

同期化によって性能関連の問題が発生する可能性があるため、以下のようなコードを書いて最初の1回だけ同期化することで性能を向上できる。

  • volatile: スレッド環境で1つの変数が正しく一度に動作することを保証するキーワード。
package com.devkuma.designpattern.creational.singleton.ex2;

public class SynchronizedSingleton2 {

    private volatile static Singleton2 instance;

    /**
     * アクセスできないコンストラクタ
     */
    private SynchronizedSingleton2() {
    }

    public static Singleton2 getInstance() {
        if (instance == null) {
            // 最初の1回だけインスタンスが生成される。
            synchronized (Singleton2.class) {
                if (instance == null) {
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {

        Singleton2 singleton1 = Singleton2.getInstance();
        Singleton2 singleton2 = Singleton2.getInstance();

        System.out.println(singleton1);
        System.out.println(singleton2);
    }
}