シングルトン パターンには次の特徴があります。
1. シングルトン クラスはインスタンスを 1 つだけ持つことができます。
2. シングルトン クラスは、独自の一意のインスタンスを作成する必要があります。
3. シングルトン クラスは、このインスタンスを他のすべてのオブジェクトに提供する必要があります。
シングルトン パターンでは、クラスのインスタンスが 1 つだけ存在することが保証され、クラス自体がインスタンス化されて、このインスタンスがシステム全体に提供されます。コンピュータ システムでは、スレッド プール、キャッシュ、ログ オブジェクト、ダイアログ ボックス、プリンタ、グラフィック カード ドライバ オブジェクトはシングルトンとして設計されることがよくあります。これらのアプリケーションはすべて、多かれ少なかれリソース マネージャーの機能を備えています。各コンピュータには複数のプリンタを搭載できますが、2 つの印刷ジョブが同時にプリンタに出力されることを防ぐために、存在できるプリンタ スプーラは 1 つだけです。各コンピュータは複数の通信ポートを持つことができ、システムはこれらの通信ポートを集中管理して、1 つの通信ポートが 2 つの要求によって同時に呼び出されないようにする必要があります。つまり、シングルトン モードを選択する目的は、矛盾した状態を回避し、長期的なポリシーを回避することです。
まず、古典的なシングルトンの実装を見てみましょう。
次のようにコードをコピーします。
パブリック クラス シングルトン {
プライベート静的シングルトン uniqueInstance = null;
プライベートシングルトン() {
// インスタンス化を無効にするためだけに存在します。
}
public static Singleton getInstance() { if (uniqueInstance == null) {
uniqueInstance = 新しい Singleton();
}
uniqueInstance を返します。
}
// 他のメソッド...
}
Singleton は、構築メソッドをプライベートに制限することで、クラスが外部でインスタンス化されるのを回避します。同じ仮想マシンのスコープ内では、Singleton の唯一のインスタンスには getInstance() メソッドを通じてのみアクセスできます。 (実際、Java リフレクション メカニズムを通じてプライベート コンストラクターを使用してクラスをインスタンス化することができます。これにより、基本的にすべての Java シングルトン実装が無効になります。この問題についてはここでは説明しません。リフレクション メカニズムは存在しないものとして考えてみましょう。)
ただし、上記の実装ではスレッドの安全性の問題は考慮されていません。いわゆるスレッド セーフティとは、コードが配置されているプロセスで複数のスレッドが同時に実行されている場合、これらのスレッドがこのコードを同時に実行できることを意味します。各実行の結果がシングルスレッド実行の結果と同じであり、他の変数の値が予想どおり同じである場合、それはスレッドセーフです。言い換えれば、クラスまたはプログラムによって提供されるインターフェイスは、スレッドのアトミックな操作であるか、複数のスレッド間の切り替えによってインターフェイスの実行結果があいまいになることはありません。これは、同期の問題を考慮する必要がないことを意味します。明らかに、上記の実装はスレッド セーフの要件を満たしておらず、複数のシングルトン インスタンスが同時環境に出現する可能性があります。
次のようにコードをコピーします。
//ハングリースタイルのシングルトンクラス。クラスの初期化時に自動的にインスタンス化されます。
パブリック クラス Singleton1 {
//プライベートのデフォルトコンストラクター
プライベート Singleton1() {}
//すでにそれ自体でインスタンス化されています
プライベート静的最終シングルトン 1 シングル = 新しいシングルトン 1();
//静的ファクトリーメソッド
public static Singleton1 getInstance() {
シングルを返します。
}
}
// 最初に呼び出されたときに遅延シングルトン クラスをインスタンス化します。
パブリック クラス Singleton2 {
//プライベートのデフォルトコンストラクター
プライベート Singleton2() {}
//注意してください、ここには最終的なものはありません
プライベート静的Singleton2シングル=null;
//静的ファクトリーメソッド
public synchronized static Singleton2 getInstance() {
if (単一 == null) {
シングル = 新しい Singleton2();
}
シングルを返します。
}
}