この記事の内容は主に GoF のデザインパターンと Yan Hon の「Java とパターン」からの抜粋です。
シングルトン モード。シングルトン モードとも呼ばれます。定義は次のとおりです (GoF デザイン パターンを参照)。
1. 用意:
クラスのインスタンスが 1 つだけであることを確認し、そのインスタンスへのグローバル アクセス ポイントを提供します。
2. 参加者:
• シングルトン クラス (Singleton)
- クライアントがその唯一のインスタンスにアクセスできるようにする getInstance() オペレーションを定義します。getInstance() はクラス操作 (静的メソッド) です。
— 独自の一意のインスタンスの作成を担当する場合があります。
3. 構造図:
この定義によれば、クライアントは Singleton クラスの getInstance() メソッド操作を通じてのみ Singleton インスタンスにアクセスできます。
Yan Hon の「Java とパターン」では、次の定義が与えられています。
シングルトン パターンは、クラスがインスタンスを 1 つだけ持つことを保証し、クラス自体をインスタンス化し、このインスタンスをシステム全体に提供します。このクラスをシングルトンクラスと呼びます。
シングルトン パターンをいつ使用するか?
この定義から、システムがクラスのインスタンスを 1 つだけ持つ必要がある場合にのみ、シングルトン パターンを使用する必要があることがわかります。
シングルトン パターンのキーポイントと実装:
1. シングルトン クラスは、シングルトン クラス タイプの静的メンバー変数であるインスタンスを 1 つだけ持つことができます。
2. シングルトン クラスは独自の一意のインスタンスのみを作成できます。コンストラクターはプライベートである必要があります。
3. シングルトン クラスは、このインスタンスを他のすべてのオブジェクトに提供する必要があります。シングルトン クラス独自のインスタンスを返す共通の静的メソッドがあります。
Java では、シングルトン パターンには、eagerとLazy の 2 つの形式があります。
対応するコードは次のとおりです。
お腹が空いた中華風(熱心)
シングルトン クラスは、ロード時に自身をインスタンス化します。
/*
* 饿汉(eager)式单例类
*/
public class EagerSingleton {
// 一个静态的单例类类型的成员变量
private static final EagerSingleton m_instance = new EagerSingleton();
/**
* 私有构造函数,保证外界无法直接实例化
*/
private EagerSingleton(){}
/**
* 静态工厂方法,返回单例类自己的实例
*/
public static EagerSingleton getInstance(){
return m_instance;
}
}
怠け者
シングルトン クラスは、初めて参照されるときにそれ自体をインスタンス化します。
遅延アプローチでは、複数のスレッドが初めてこのクラスを同時に参照するときに、アクセス制限を処理する必要があります。
/*
* 懒汉(lazy)式单例类
*/
public class LazySingleton {
// 一个静态的单例类类型的成员变量
private static LazySingleton m_instance = null;
/**
* 私有构造函数,保证外界无法直接实例化
*/
private LazySingleton(){}
/**
* 静态工厂方法,返回单例类自己的实例,
* 使用了同步化synchronized,和一个if判断,来处理多线程环境。
*/
synchronized public static LazySingleton getInstance(){
if(m_instance == null){
m_instance = new LazySingleton();
}
return m_instance;
}
}
ダブルチェックされたサンプルを使用するシングルトン パターンの別の形式もありますが、Yan Hon の「JAVA とパターン」では、ダブルチェックされたサンプルは Java コンパイラには適さないことが指摘されています。
基本的な理由は、Java コンパイラでは、LazySingleton クラスの初期化と m_instance の変数割り当ての順序が予測できないためです。スレッドが同期せずに m_instance 参照を読み取り、このオブジェクトのメソッドを呼び出すと、オブジェクトの初期化プロセスが完了していないことがわかり、クラッシュが発生する可能性があります。
Java のメモリ モデルのため、ダブルチェック ロックは Java には適していません。 ダブルチェック ロックとシングルトン モードを参照してください。