38

シングルトンが次のように実装されている場合、

class Singleton {
    private static Singleton instance = new Singleton();

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

この実装は、遅延初期化アプローチとどう違うのですか? この場合、クラスがロードされたときにインスタンスが作成され、クラス自体は最初のアクティブな使用時にのみロードされます (たとえば、Singleton.getInstance() は、インスタンス Singleton singleton = null; を宣言するときではありません)。

遅延初期化アプローチでも、インスタンスは getInstance() の呼び出しで作成されます

ここで何か不足していますか?

4

5 に答える 5

27

遅延初期化では、クラスがロードされたときではなく、必要なときにのみインスタンスを作成します。したがって、不要なオブジェクトの作成を回避できます。そうは言っても、他にも考慮すべき点があります。遅延初期化では、パブリック API を指定してインスタンスを取得します。マルチスレッド環境では、不要なオブジェクトの作成を避けるという課題が生じます。すでに作成されたオブジェクトをチェックするために不要なロックを行う同期ブロックを配置します。したがって、この場合はパフォーマンスの問題になります。

したがって、オブジェクトの作成に大量のメモリが必要でなく、ほとんどの場合アプリケーションで使用されることが確実である場合は、静的初期化で作成することをお勧めします。また、この場合、インスタンスを final にすることを忘れないでください。これにより、オブジェクトの作成が適切かつ全体的にメイン メモリに反映されるようになります。これは、マルチスレッド環境で重要です。

Singleton+ Lazy Loading+ Multithreaded Environment のケースについては、IBM のこのチュートリアルを参照してください。

===============2018年9月9日に編集====================

また、ここでオンデマンド パターンのオブジェクト作成も確認する必要があります。

于 2011-10-17T06:51:51.177 に答える
17

他の静的メソッドまたは静的メンバー変数を呼び出して、シングルトン インスタンスをロードすることもできます。

class Logger {     
   private static Logger instance = new Logger(); 
   public static String LOG_LINE_SEPERATOR =  
      System.getProperty("line.separator");
   public static Logger getInstance() {  
          return instance;     
   } 

   public static String logPattern() {
       return null;
   }
} 

...

Logger.LOG_LINE_SEPERATOR; // load Logger instance or
Logger.logPattern(); // load Logger instance
于 2011-10-17T07:00:26.340 に答える
8

あなたが言及した理由により、これは

enum Singleton {
    INSTANCE;
}

遅延初期化の使用は、クラスが初期化される可能性があることを懸念しているが、その時点でシングルトンをロードしたくない場合にのみ役立ちます。ほとんどの場合、これはオーバーキルです。

注: クラスを参照するだけでは、クラスは初期化されません。

たとえば、何らかの条件が設定されるまで初期化できない、不適切に作成されたクラスがあるとします。この場合n、非ゼロでなければなりません。

public class Main {
    public static void main(String ... args) {
        Class c= LazyLoaded.class;
        System.out.println(c);
    }

    static class LazyLoaded {
        static int n = 0;
        static {
            System.out.println("Inverse "+1000/n);
        }
    }
}

版画

class Main$LazyLoaded
于 2011-10-17T07:47:28.697 に答える
1

まず、シングルトン パターンが多用されています。「何かの1つ」が必要な場合に本当にやりたいことは、選択したDIフレームワークでそれをシングルトンとして宣言することです。これは事実上構成主導型の熱心なシングルトンであり、モックを注入して適切なテストを行うためのオプションを解放します。

なぜ遅延ロードしないのですか?あなたのクラスが大規模な初期化ルーチンを構築していない限り (これはアンチパターンでもあると私は主張します)、遅延読み込みには利点がなく、多くの欠点があります。複雑さを増すだけであり、正しく行われなければプログラムが壊れる可能性があります。正しい方法 (必要な場合) は、Initialization-on-demand holder イディオムを使用することです。

于 2017-10-19T19:02:32.933 に答える