0

私はJavaでシングルトンパターンを実装する2つの方法を知っており、どちらが優れているのか、そしてその理由を考えています。

最初の方法は次のとおりです。

  1. クラスprivateのコンストラクタを宣言します
  2. クラス内のすべてを静的にする-基本的に、クラスインスタンス自体をシングルトンにする

2番目の方法は次のとおりです。

  1. クラスprivateのコンストラクタを宣言します
  2. シングルトン(クラスのインスタンスである可能性があります)を保持する静的メンバーがあります
  3. 静的なgetInstance()メソッドがあります

2番目のアプローチが最も一般的ですが、最初のアプローチの方がコードの可読性が向上する可能性があると思う傾向があります。どちらのアプローチも実行時の複雑さにおいて同様に効率的であるように思われるため、2番目のアプローチがはるかに一般的である理由を実際に理解することはできません。より良い実践と考えられています...

私を啓発します!

4

6 に答える 6

5

最初のアプローチはシングルトンではありません。シングルトンは、正確に1つのインスタンス、それ以上でもそれ以下でも存在できないクラスです。最初のものは、「静的クラス」、「ユーティリティクラス」、または「インスタンス化できないクラス」と呼ばれることもあります。

ユーティリティクラスでは実行できない「実際の」シングルトンで実行できることがいくつかあります。たとえば、インターフェイスを実装したり、別のクラスを拡張したりするシングルトンを作成できます。all-static-methodsではそれを行うことはできません。all-static-methodsクラスは、一般に、オブジェクト指向の設計分析が行われなかったことの証拠です。

Javaでシングルトンパターンを実装する方法がいくつあるかについては、実際にはかなりの数の興味深い方法があります。さまざまな言語機能を使用して、絶対に必要になるまで初期化を延期します。クラスの読み込み、列挙、または単に同期されたブロックとif

于 2012-07-31T01:07:28.853 に答える
3

シングルトンを使用する他のクラスのテスト容易性は、静的メソッドによって妨げられます。インスタンスを使用すると、モックオブジェクトまたは他の形式のテストダブルを置き換えることができます。

于 2012-07-31T01:16:00.117 に答える
1

オブジェクトベースのシングルトンの利点

  1. あなたの「シングルトン」は、想像を絶する状況下で、非シングルトンになるのでしょうか?おそらく、スレッドごと、接続ごと、またはその他の分類が必要になるでしょうか。ドア#2は、コードを書き直すことなく、未来を残します。

  2. シングルトンを持っているかもしれませんが、そのシングルトンの実装は1つだけですか?一般的なパターンは、ファクトリメソッドでランタイム環境を調べ、シングルトンによって提供される「サービス」のどの実装が適切かを判断することです。commons-logging LogFactoryは、このタイプのシングルトンの例です。

于 2012-07-31T01:08:38.463 に答える
0

シングルトンパターンを実装するための興味深い方法はいくつかあります。私が読んだそれらの実装のいくつかを思い出させてください:

  1. あなたがあなたの質問で言及した2番目のアプローチ。(スレッドセーフではありません)
  2. マルチスレッドアプリケーションを開発する場合、ロックを使用する必要がある場合があります(単純なスレッドセーフ)

    パブリックシールクラスシングルトン{静的シングルトンインスタンス=null; static readonly object padlock = new object();

    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
    

    }

  3. ロックを再確認する

    パブリックシールクラスシングルトン{静的シングルトンインスタンス=null; static readonly object padlock = new object();

    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                lock (padlock)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    }

  4. 怠惰ではありませんが、ロックを使用せずにスレッドセーフです

    パブリックシールクラスシングルトン{静的読み取り専用シングルトンインスタンス=新しいシングルトン();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }
    
    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
    

    }

  5. 完全に怠惰な初期化

    パブリックシールクラスSingleton{Singleton(){}

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }
    
    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }
    
        internal static readonly Singleton instance = new Singleton();
    }
    

    }

3番目のアプローチはjava.BecosJavaメモリモデルでは機能しません。新しいオブジェクトへの参照がインスタンスに割り当てられる前に、コンストラクタが完了することを保証しません。

これがお役に立てば幸いです。

于 2012-07-31T04:57:59.593 に答える
0

あなたの質問があれば、そうです。

なぜこれが#2なのか

public class MySingleton {

  static private MySingleton instance=new MySingleton();

  private MySingleton() {}

  static public MySingleton getInstance() { return instance; }

}

#1より良い

...申し訳ありませんが、最初のポイントがわかりません...->実際に他のコメントから読んでいます。確かに、静的メソッドがあるからといって、シングルトンがあるわけではありません。したがって、比較は公平ではありません;-/

それが何であれ、#2が優れている理由は、マルチスレッドによるものです。静的初期化子からシングルトンが初期化される場合、jvmは1つのスレッドのみがクラスをインスタンス化することを確認します。

于 2012-07-31T01:11:50.100 に答える
-2

おそらく、列挙型を使用してシングルトンを実装することを検討してください。

public enum Singleton {
INSTANCE;

public void doStuff() {
    System.out.println("Whoopee");
}
}

そしてそれを次のように呼びますSingleton.INSTANCE.doStuff()

これは、JoshBlochの著書EffectiveJavaで推奨されています。

于 2012-07-31T01:07:11.350 に答える