2016-11-01 3 views
0

static synchronized getInstanceメソッドを使用するシングルトンの適切な使用法とその理由は何ですか?例えばSingleton getInstanceメソッドの適切な使用

mySingletonフィールドとクラス全体で使用されるであろう

MySingleton mySingleton = MySingleton.getInstance(); 
..... 
mySingleton.doSomething(); 

MySingleton.getInstance().doSomething(); 

EDIT対

:適切なことで、私はスタイルとスレッドの安全性をコーディング意味。

+1

理想的には、シングルトンをまったく使用しないでください。私がしなければならないのは、 'enum'を使うことです。その場合は' MySingleton.INSTANCE.doSomething() 'と書いてください。 –

+1

これらの2つの例は同じですが、@PeterLawreyはシングルトンの列挙を勧めます。 –

+0

「適切な」定義 - 具体的に何を求めていますか?インスタンスを取得して後で使用する最初の例以外は同じです。 –

答えて

1

可能であればシングルトンを回避するための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つのバージョン:使用する機能がインターフェイスでサポートされ、実装タイプではなくそのインターフェイスに対してコード化されていることを確認してください。それはあなたのコードをテスト可能にします。

0

私は、クラス内のすべてのシングルトンに対してフィールドを定義する方が良いと思います。したがって、最初のn行だけを見れば、システム内のシングルトンに対するクラスの依存関係を簡単に見つけることができます。それは、クラスのカップリングを理解するのに役立ちます。

また、シングルトンのフィールドを定義することで、テストが容易になります。万一、シングルトンのメソッドをインタフェースに移動できる場合は、シングルトンのスタブクラスを定義し、テストコードのスタブシングルトンに注入することができます。

スレッドセーフティパーツの場合、シングルトンがスレッドセーフな場合は問題ありません。

1

シングルトンを使用するよりもよりよい解決策を使用することですdependency injection

class MyClass { 
    private final MySingleton mySingleton; 

    MyClass(MySingleton mySingleton) { 
    this.mySingleton = mySingleton; 
    } 

    // Use mySingleton in instance methods as required. 
} 

ここでの利点は、それがシングルトンだ事実はない関連性があるということです - それはシングルトンすることができますが、それはdoesnのtは必要があります。

私はフィールドmySingletonと呼んでいますが、それはあなたの質問でそれを呼んだものですが、もはやそれが本当にシングルトンである必要はありません:唯一のことは、人生を気にする必要はありませんインスタンスのサイクル。

これは、質問に記載されているいずれかの方法で行った場合に存在する、MyClassMySingletonの静的結合を破ります。これにより、他の利点の中でMyClassのテストが容易になります。

+0

私はシングルトンを濫用してはならないことに同意します。さて、DIは依存性コンテナを必要とし、シングルトンは依存性コンテナを必要としません。依存関係コンテナを使用している場合、またはそのコンテナを使用したい場合、そのアイデアは良いですが、それを必要とせず、3〜4つのクラシックシングルトンがプロジェクトにある場合、なぜそのオーバーヘッドを追加しますか?シングルトンをテストするのはDIよりも難しいですが、リフレクションでは非常に再生可能です。 – davidxxx

0

誰かがシングルトンをインスタンス化する必要があります。これは一度だけ行う必要があります。ここで糸が安全に遊びに来る。

private static volatile SingletonClass myInstance; 

public static SingletonClass getInstance() 
{ 
    if (myInstance == null) 
    { 
     synchronized(SingletonClass.class) 
     { 
      if (myInstance == null) 
      { 
       myInstance = new SingletonClass(); 
      } 
     } 
    } 

    return myInstance; 
} 

これは「二重のチェックをロック」と呼ばれている:異なるスレッドが同時にほぼ

SingletonClass.getInstance(); 

を呼ぶ可能性がある場合は、シングルトンのインスタンス化は次のように保護する必要があります。変数はvolatileでなければなりません。

SingletonClassのメソッドがスレッド間で状態を共有している場合(たとえば、あるスレッドによって書き込まれ、別のスレッドによって読み込まれたメンバーがある場合)、同期時にさらに注意を払う必要があります。しかし、これは一般的であり、シングルトンパターンとは関係がありません。

あなたの質問 "XY.getInstance()。doSomething()"とそれに後でアクセスするための参照を自分のメンバーに保存することとの違いは何ですか:それはただ(マイナー) ifステートメント、return)。しかし、IMOではこれは無視できません。なぜなら、長期的には、Javaオプティマイザがこれをインラインで実行するからです。一方、参照を保持すると、シングルトンに頻繁にアクセスすると、コードが短くて読みやすくなります。最後には味の問題です。