可能であればシングルトンを回避するためのAndy Turnerの答えに同意しますが、これを完全にするためにこれを追加します。静的な同期化されたgetInstanceメソッドは過去の遺物です。それを必要としない少なくとも3つのシングルトンパターンの実装があります。
A)熱心なシングルトン
public class EagerSingleton{
private EagerSingleton(){}
private static final EagerSingleton INSTANCE = new EagerSingleton();
public static EagerSingleton getInstance(){ return INSTANCE; }
}
あなたがそのタイプの変数を宣言することによって(例えば、任意の方法でクラスEagerSingletonを参照するたびにこれは、クラス・ロード時に初期化されます)。
b)の怠惰なシングルトン
public class LazySingleton{
private LazySingleton(){}
private static class Holder{
private static final LazySingleton INSTANCE = new LazySingleton();
}
public static LazySingleton getInstance(){ return Holder.INSTANCE; }
}
これは、通話時間、あなたはメソッドのgetInstance(コール1回目)で初期化されます。クラスローダーがホルダークラスをロードし、INSTANCEフィールドを初期化するようになりました。同期された方法でそれを行うことが保証されています。あなたのシングルトンが高価な設定をしている場合は、このバージョンを使用し、必ずしも必要ではありません。
c)に列挙シングルトン
public enum EnumSingleton{
INSTANCE;
// and if you want, you can add the method, too, but it's
// unnecessary:
public static EnumSingleton getInstance(){ return INSTANCE; }
}
列挙項目そのユニークさが(実行時に、シングルトンはクラスローダごとに一意であること、およびコンパイル時だけでなく、実行時に保証されている。すなわち、コンパイル時定数でありますすべてのバージョンに適用されます)。要件が既存のクラスから拡張されない限り、これは最善の方法です。
列挙バージョンはあなたの自由のために他の多くの機能を提供します:
- は、デシリアライズ攻撃に対する
- 防衛
- multitonサポートが(ちょうど別の列挙型を追加し、箱から出して/のhashCode /のtoStringの実装に等しいですアイテム)
次回は、誰かがダブルチェックされたロック機構などを書いているのを見て、それがあまりにも複雑で技術的になっていると教えてくださいal。クラスローダーがあなたのために仕事をするようにしましょう。
すべての3つのバージョン:使用する機能がインターフェイスでサポートされ、実装タイプではなくそのインターフェイスに対してコード化されていることを確認してください。それはあなたのコードをテスト可能にします。
理想的には、シングルトンをまったく使用しないでください。私がしなければならないのは、 'enum'を使うことです。その場合は' MySingleton.INSTANCE.doSomething() 'と書いてください。 –
これらの2つの例は同じですが、@PeterLawreyはシングルトンの列挙を勧めます。 –
「適切な」定義 - 具体的に何を求めていますか?インスタンスを取得して後で使用する最初の例以外は同じです。 –