静的クラスとシングルトンパターンの違いは?


1768

静的クラスとシングルトンパターンの間に実際の(つまり、実用的な)違いは何ですか?

どちらもインスタンス化せずに呼び出すことができ、どちらも「インスタンス」を1つだけ提供し、どちらもスレッドセーフではありません。他に違いはありますか?


4
言語の実装と使用パターンによっては、シングルトン、使用getInstance()するたびにメソッドを呼び出すオーバーヘッドがあるため、効率が低下する可能性があります(ほとんどの場合、問題ではありません)。
phpが多すぎる

5
すでにたくさんの答えがあります。これは実際にはsingletonstaticメソッドが単なる関数であり、非OOエンティティであるオブジェクトです。
fastcodejava '16年

4
実装によって異なります。.csharpindepth.com
Articles/General/

4
サードパーティがクラスの実装を提供できるようにする場合は、違いがあります。この場合、通常はFactoryパターンも必要です。agiletribe.wordpress.com/2013/10/08/…を
AgilePro

IMOこの答えは非常によく、それを合計stackoverflow.com/questions/14097656/...
デイブ

回答:


1251

シングルトンメソッドまたは静的メソッドのいずれかがスレッドセーフではないとはどういう意味ですか?通常、両方がすべきスレッドセーフになるように実装するがあります。

シングルトンと一連の静的メソッドの大きな違いは、シングルトンがインターフェイスを実装できる(または、私の経験ではそれほど一般的ではないが、有用な基本クラスから派生できる)ため、シングルトンを「別のちょうど」のように渡すことができることです。 "実装。


29
まあ、あなたがそれを好むなら、どちらも本質的にスレッドセーフではありません、あなたはそれらを両方ともスレッドセーフにする必要があるので、そこに違いはありません。
ホルヘコルドバ、

119
あなたが何かの例与えることができている不変の種類以外の、本質的にスレッドセーフを、?
Jon Skeet、

26
スキートへ:シングルトンはスレッドセーフではないと言っている人は、シングルトンが常に不必要にスレッド間で共有されることを意味し、スタックオブジェクトは必要なときに共有されるため、不要な同期を行う必要がありません。

45
@Geek:シングルトンがインターフェイスを実装し、パラメーターとしてを受け取るFooメソッドがあるFooとします。この設定により、呼び出し元はシングルトンを実装として使用することを選択できます。または、別の実装を使用することもできます。この方法はシングルトンから切り離されています。クラスに静的メソッドしかない状況と比較してください。これらのメソッドを呼び出す必要のあるすべてのコードは、静的メソッドを含むクラスを指定する必要があるため、クラスに密結合されています。
Jon Skeet 2013

10
@AmirBareket:シングルトンデザインパターンによると、シングルトンではありません。ただし、クラス自体が複数のインスタンスの作成を許可している場合、ファクトリの動作に関係なく、シングルトンIMOではありません。
Jon Skeet、2014

476

本当の答えは、ここの別のフォーラムでの Jon Skeetによるものです

シングルトンは、作成された単一のインスタンスへのアクセスを許可します。そのインスタンス(または、そのインスタンスへの参照)は、パラメーターとして他のメソッドに渡し、通常のオブジェクトとして扱うことができます。

静的クラスは静的メソッドのみを許可します。


64
静的getInstance()メソッドを呼び出すことで、どこからでも同じインスタンスにアクセスできるのに、なぜシングルトンをパラメータとして渡すのでしょうか。
Henrique Ordine

23
@HenriqueOrdineそれで、それは既存のコードに適合し、インターフェースを提供することができますか?

6
@HenriqueOrdine彼らは静的メソッドについてのクラスではなく、静的クラスについて話しています。静的クラスはインスタンス化できません。それでも、静的メソッドを含む(非静的)クラスのインスタンスを渡す場合、インスタンスで静的メソッドを呼び出すことはできません。
ゴラン

3
静的クラスとは何ですか?少なくともJavaでは、そのようなことはありません。
Henrique Ordine 2012

16
@ゴラン私は最初あなたの言葉にとても戸惑いました。「インスタンスで静的メソッドを呼び出すことはできません」と述べました。「インスタンス化されたオブジェクトへの参照がある場合、そのオブジェクトが持つ可能性のある静的メソッドを呼び出すことはできません。」もちろん、それは間違いです。もう一度何度か読んだ後、「静的メソッドの内部からはクラスの非静的オブジェクトにアクセスできない」という意味で正しいと思います。この答えに出くわしてあなたのコメントを読んだ、これらの概念に不慣れな人のためにそれを明確にしたいです。
Andrew Steitz 2013

359
  1. シングルトンオブジェクトはヒープに格納されますが、静的オブジェクトはスタックに格納されます
  2. クローンできます(設計者がそれを禁止していない場合)シングルトンオブジェクトを、私たちは、静的クラスオブジェクトのクローンを作成することはできません。
  3. シングルトンクラスはOOP(オブジェクト指向の原則)に従いますが、静的クラスはそうではありません。
  4. 実装できます interfaceシングルトンクラスでが、クラスの静的メソッド(またはC#などstatic class)できません。

99
2番目のステートメントは間違っています。シングルトンオブジェクトのクローンは作成できません。シングルトン実装はこれを拒否する必要があります。本当にシングルトンを複製できるなら、それはシングルトンではありません。
Alexander Yancharuk 2013

19
これは正解ではありません。シングルトンもスタティックもスタックを使用しません。
AgilePro 2013年

72
#1は重要ではありません。#2は欠陥のある実装を示しています。#3は完全に不当です。
ケーシー

31
静的オブジェクトをスタックに保存するにはどうすればよいですか?メソッドを呼び出すと、新しいスタックフレームが作成され、メソッドのローカル変数が格納されます。このスタックフレームは、メソッドが戻ると削除され、ローカル変数は失われます。確かにスタックは高速ですが、静的オブジェクトの格納には適していません。
mike_m 2014年

23
これについての賛成票の数がわかりません。1)シングルトンをスタックに格納する必要があるのはなぜですか?C#やJavaなどのマネージ言語では、ローカルメソッド変数/パラメーターを除いて、データはマネージヒープに格納されます。2)クローンできる場合は、適切に実装されたシングルトンではありません。3)シングルトンはOOPアンチパターンとして知られています。つまり、可能であれば避けるべきもの。4)これが正しい唯一のことです。
Groo

152

シングルトンパターンには、静的クラスに比べていくつかの利点があります。まず、シングルトンはクラスを拡張してインターフェースを実装できますが、静的クラスはできません(クラスを拡張することはできますが、インスタンスメンバーを継承しません)。シングルトンはレイジーまたは非同期で初期化できますが、静的クラスは通常、最初にロードされたときに初期化されるため、クラスローダーの問題が発生する可能性があります。ただし、最も重要な利点は、シングルトンは、ユーザーにインスタンスが1つしかないと想定させることなく、ポリモーフィックに処理できることです。


10
+1は実用的で実用的なポイントです。シングルトンパターンは一般的に過剰に使用されますが、適切な状況がいくつかあります。参照: agiletribe.wordpress.com/2013/10/08/...
AgilePro

3
あなたは多態性であることの利点について正しいです。これが最も重要なポイントである
アフマド

ネストされた静的クラスはインターフェースを実装できます。それをコーディングしてみてください、動作します。エラーなしでコードをコンパイルできました。
nanosoft 2016年

75

staticクラスは、状態を必要とするもののためのものではありません。たくさんの機能をまとめるMath(つまりUtilsプロジェクトで)のに便利です。したがって、クラス名は、関数を見つけるための手がかりを与えるだけで、それ以上のものはありません。

Singletonは私のお気に入りのパターンであり、私はそれを使用して何かを一元的に管理します。staticクラスよりも柔軟性があり、状態を維持できます。インターフェイスを実装し、他のクラスから継承し、継承を許可できます。

staticとを選択するための私のルールsingleton

まとめておくべき機能がたくさんある場合は、それstaticが選択です。いくつかのリソースへの単一のアクセスを必要とする他のものは、として実装できますsingleton


16
なぜ静的クラスは状態を保存する必要があることを何もすべきではないのですか?
Trisped

12
@Trisped:初期化もファイナライズも正確に制御できません。
Xaqron

7
「シングルトンは私のお気に入りのパターン」で私を失った。シングルトンは非常に鋭い角であるため、パターンと同様にアンチパターンと考える必要があります。ほとんどのシングルトン実装が壊れているため、静的状態がシングルトンよりも「単一アクセス」である場合、クラスには静的状態、つまり単一アクセスもあります。静的は一意であるという定義に恵まれている一方で、シングルトンのクローンを作成できます。
PoweredByRice 2017

1
状態を維持するとはどういう意味ですか?状態とは?
カイルデラニー

2
@KyleDelaney:State通常、時間とともに変化するオブジェクトのさまざまなプロパティの組み合わせです。Googleで正式な定義を行うことができます。
Xaqron

65

静的クラス:-

  1. 静的クラスのインスタンスは作成できません。

  2. クラスを含むプログラムまたは名前空間が読み込まれると、.NET Framework共通言語ランタイム(CLR)によって自動的に読み込まれます。

  3. 静的クラスはコンストラクタを持つことができません。

  4. 静的クラスをメソッドに渡すことはできません。

  5. StaticクラスをC#の別のStaticクラスに継承することはできません。

  6. すべての静的メソッドを持つクラス。

  7. パフォーマンスの向上(静的メソッドはコンパイル時に結合されます)

シングルトン:-

  1. オブジェクトのインスタンスを1つ作成して再利用できます。

  2. シングルトンインスタンスは、ユーザーが要求したときに初めて作成されます。

  3. シングルトンクラスはコンストラクタを持つことができます。

  4. シングルトンクラスのオブジェクトを作成してメソッドに渡すことができます。

  5. シングルトンクラスは継承の制限を何も言いません。

  6. シングルトンクラスのオブジェクトは破棄できますが、静的クラスは破棄できません。

  7. メソッドはオーバーライドできます。

  8. 必要なときに遅延ロードできます(静的クラスは常にロードされます)。

  9. インターフェイスを実装できます(静的クラスはインターフェイスを実装できません)。


13
静的クラスにはコンストラクタがあります:msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
Tomer Arazy

2
はい、staticはそのクラスの内部にあるコンストラクタを持つことができます。これは、クラスの静的メソッドが呼び出されると呼び出されます。
rahulmr 2017年

コンパイル時のシングルトンの場合、それはHEAPメモリに格納されますが、一度インスタンス化されると、STACKに格納されますか?
Luminous_Dev

@Luminous_Devいいえ。シングルトンインスタンスは、結局のところオブジェクトインスタンスです。間違いなくヒープに格納されます。
2018年

1
@rahulmr重要な違い:最初の(別名のみ)インスタンスが作成される前にコンストラクターも呼び出されます。
CoolOppo 2018

53

静的クラスとは、静的メソッドのみを持つクラスであり、「関数」の方がいいでしょう。静的クラスに組み込まれたデザインスタイルは、純粋に手続き型です。

一方、シングルトンは、OOデザインに固有のパターンです。これは、オブジェクトのインスタンスであり(ポリモーフィズムなど、それに固有のすべての可能性があります)、その存続期間全体でその特定の役割のインスタンスが1つしかないことを保証する作成手順があります。


1
ポリモーフィズムはシングルトンとはまったく関係しません

32
だからあなたは思います。私は違うと思います。;)たとえば、インターフェイスを返すシングルトンファクトリを想像してみてください。あなたはISingleton(そしてそれは永遠に同じものです)を取得していることを知っていますが、必ずしもどの実装であるとは限りません。
モレンディル2009

ネストされた静的クラスはインスタンスメソッドも持つことができ、静的メソッドのみを持つことに限定されません。コード化して見ることができます。
nanosoft 2016年

より優れたオブジェクトモデル(Rubyなど)を持つ言語では、クラスもオブジェクトです。静的クラスの「純粋に手続き型」の側面は、言語によって課される任意の制限です。
最大の

36

シングルトンパターンでは、派生型のインスタンスとしてシングルトンを作成できますが、静的クラスでは作成できません。

簡単な例:

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer

39
これは実際にはシングルトンパターンではなく、ファクトリーのように見えます。
vava

10
実際には、この2つの基本的な違いは、シングルトンが単一のオブジェクトを「キャッシュ」し、同じオブジェクトを返します(参照する)ことです。Factoryパターンは新しいインスタンスを作成します。
ミスティック

12
次に、それはプロキシシングルトンです:)
vava

3
うーん、私はこのシングルトンの種類をMonoStateとして知っています。
Huppie 2009

例は工場パターンです
Rajavel D 2014

26

ジョン・スキートの回答を拡張するには

シングルトンと多くの静的メソッドの大きな違いは、シングルトンがインターフェイスを実装できる(またはIMEとしては一般的ではないものの、有用な基本クラスから派生できる)ため、シングルトンを「別の」実装であるかのように渡すことができることです。

シングルトンは、クラスをユニットテストするときに扱いやすくなります。シングルトンをパラメーター(コンストラクター、セッター、またはメソッド)として渡す場所はどこでも、代わりにシングルトンのモックバージョンまたはスタブバージョンを置き換えることができます。


シングルトンを直接モックすることはできないと思います。シングルトンとモッククラスの両方が実装するインターフェースを宣言する必要はありませんか?
Ellen Spertus 14

@espertusシングルトンをあざけることができないのはなぜですか?mockitoの使用例MySingleton mockOfMySingleton = mock(MySingleton.class)
Mike Rylander 14

そうです、mockitoなどのリフレクションを使用するツールでモックできます。それをサブクラス化してそのメソッドをオーバーライドすることで直接モックすることはできないということです。
Ellen Spertus 14

@espertusどうして?テストするオブジェクトをインスタンス化するときは、オリジナルを使用した場所にシングルトンのサブクラス実装を代入できます。例:new ClazzToTest(mockSingleton);
マイクライランダー14

私はMockitoを使用していませんが、リフレクションを使用することを除いて、シングルトンの場合のように、プライベートコンストラクターを持つクラスをどのようにサブクラス化できますか?関連ディスカッション:stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023/...
エレン・スパータス

23

ここに良い記事があります:http : //javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

静的クラス

  • すべての静的メソッドを持つクラス。
  • パフォーマンスの向上(静的メソッドはコンパイル時に結合されます)
  • メソッドをオーバーライドすることはできませんが、メソッドの非表示を使用できます。(Javaでのメソッドの隠蔽とは何か?JavaDocの説明でさえ混乱を招く

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

シングルトン

要約すると、utilメソッドを保持するために静的クラスのみを使用し、それ以外にはすべてシングルトンを使用します。


編集


4
Javaについては知りませんが、.Netでは、最後の2つの点が正しくありません。静的クラスは静的プロパティとフィールドを参照できるため、状態は同じです。そして、それらは遅延ロードされます-静的コンストラクターは次の場合に実行されます:1)クラスのインスタンスが作成されます。2)クラスの静的メンバーのいずれかが参照されている。1は適用されず、2のままになります。したがって、静的クラスは、最初に使用されるまでロードされません。
jmoreno

1
静的クラスの場合、静的メソッドをオーバーライドすることはできませんが、静的メソッドを親から非表示にすることができます。
Max Peng

もしそうならどうAnimal animal = new Cat();なりanimal.foo();ますか?
Luminous_Dev

@jmoreno静的クラスは、初めて使用するまで読み込まれませんか?コンパイル時にスタックメモリに格納されていると思います。そして、それは即座にアクセスされます。
Luminous_Dev

@Luminous_Dev:少なくとも.netの場合、静的クラスには最初にアクセスしたときに実行されるコンストラクターがあるため、すぐにはアクセスできません。静的コンストラクタは、理論的には無制限の時間がかかる可能性があります。それ(または他のクラスが格納される場所)が実装の詳細である場合、それはこの質問には実際には関係ありません。
jmoreno 2017年

22

シングルトンのもう1つの利点は、簡単にシリアル化できることです。これは、状態をディスクに保存するか、リモートで送信する必要がある場合に必要になることがあります。


19

私は優れたOO理論家ではありませんが、静的クラスがシングルトンと比較して欠けている唯一のOO機能は多態性だと私は知っています。しかし、それが必要ない場合は、静的クラスを使用すると、継承(インターフェースの実装については不明)およびデータと関数のカプセル化を使用できます。

モレンディルのコメント「静的クラスに組み込まれたデザインスタイルは純粋に手続き型です」間違っているかもしれませんが、私はそうは思いません。静的メソッドでは、静的メンバーにアクセスできます。これは、単一インスタンスメンバーにアクセスするシングルトンメソッドとまったく同じです。

編集:
私は実際に今、別の違いは静的クラスがインスタンス化されるということだと考えていますプログラムの開始時にれ*、プログラムの全寿命を通じて存続するますが、シングルトンはある時点で明示的にインスタンス化され、破棄することもできます。

*または言語によっては、最初の使用時にインスタンス化される場合があると思います。


15
はい、他の誰もが、静的メソッドを持つクラスが状態を維持するために引き続き使用できるプライベート静的フィールドを持つこともできるという事実を無視しているようです(そしてそれらの一部をパブリック静的セッター/ゲッターを介してクライアントコードに公開します)。
user289463

17

ジョンのポイントを説明するために、ロガーが静的クラスでSomeClassある場合、以下に示すことは実行できません。クラスは、ILogger実装のインスタンスがコンストラクターに渡されることを期待しています。

シングルトンクラスは、依存性注入を可能にするために重要です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}

13

シングルトンはインスタンス化された通常のクラスですが、クライアントコードから間接的に一度だけです。静的クラスはインスタンス化されません。私の知る限り、静的メソッド(静的クラスには静的メソッドが必要)は非静的メソッドより高速です。

編集:
FxCopパフォーマンスルールの説明:「インスタンスデータにアクセスしたり、インスタンスメソッドを呼び出したりしないメソッドは、静的としてマークできます(VBで共有)。これにより、コンパイラーはこれらのメンバーに非仮想呼び出しサイトを発行し、現在のオブジェクトポインターがnull以外であることを保証する各呼び出しについて、実行時にチェックします。これにより、パフォーマンスに依存するコードの測定可能なパフォーマンスが向上する場合があります。場合によっては、現在のオブジェクトインスタンスへのアクセスの失敗が正確性の問題を表すことがあります。 "
これが静的クラスの静的メソッドにも当てはまるかどうかは、実際にはわかりません。


11

シングルトンはインスタンス化されます。インスタンス化されたインスタンスが1つしかないため、シングルトンのシングルになります。

静的クラスは、それ自体以外ではインスタンス化できません。


静的クラスは、Javaで非常にインスタンス化できます。docs.oracle.com/javase/tutorial/java/javaOO/nested.htmlをお読みください。私の回答も参照してくださいstackoverflow.com/a/37114702/1406510
nanosoft

8

主な違いは次のとおりです。

  • シングルトンにはインスタンス/オブジェクトがありますが、静的クラスは静的メソッドの集まりです
  • シングルトンは、たとえばインターフェースを介して拡張できますが、静的クラスは拡張できません。
  • 一方、SOLID原則のオープン/クローズ原則をサポートするシングルトンは継承できますが、静的クラスは継承できず、それ自体を変更する必要があります。
  • シングルトンオブジェクトはメソッドに渡すことができますが、静的クラスにはインスタンスがないため、パラメーターとして渡すことはできません。

7

シングルトンは、テストの観点からはより良いアプローチです。静的クラスとは異なり、シングルトンはインターフェイスを実装でき、モックインスタンスを使用してそれらを挿入できます。

以下の例でこれを説明します。getPrice()メソッドを使用するisGoodPrice()メソッドがあり、getPrice()をシングルトンのメソッドとして実装するとします。

getPrice機能を提供するシングルトン:

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

getPriceの使用:

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

最終的なシングルトン実装:

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

テストクラス:

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

getPrice()の実装に静的メソッドを使用する代わりの方法をとる場合、getPrice()をモックするのは困難でした。静的モックを電源モックで模擬できますが、すべての製品がそれを使用できるわけではありません。


1
これはスレッドセーフではなくなり、インターフェイス実装へのアクセス方法の点で一般的に厄介です。確かに、インターフェースがあるとテストしやすくなりますが、なぜシングルトンに悩むのでしょうか。シングルトンをまったく使用しないでください。本番用に1つのクラスを実装し、テスト用に1つの実装を用意し、実行していることに応じて適切なインスタンスを挿入します。シングルトンを呼び出し元に結合する必要はまったくありません。
Jon Skeet

フィードバックをお寄せいただきありがとうございます。スレッドセーフにするのは非常に簡単です。さらに、キャッシュの目的でシングルトンを使用します。
アミールBareket 14

1
はい、無意味なオーバーヘッドがあります。繰り返しますが、シングルトンを使用しないほうが簡単です。
Jon Skeet

6

私はこの定義に同意します:

シングル」は、アプリケーションのライフサイクル全体にわたる単一のオブジェクトを意味するため、スコープはアプリケーションレベルです。

静的スコープは、アプリケーションドメインレベルであるので、任意のオブジェクトのポインタを持っていません。

さらに、どちらもスレッドセーフになるように実装する必要があります。

興味深い他の違いを見つけることができます:シングルトンパターンと静的クラス


5

注目すべき違いの1つは、シングルトンに付属するインスタンス化の違いです。

静的クラスでは、CLRによって作成され、制御できません。シングルトンの場合、オブジェクトは、アクセスしようとした最初のインスタンスでインスタンス化されます。


4

多くの場合、特にシングルトンインスタンスが変更されないか、非常にゆっくりと変更される(例:構成を保持する)場合、これら2つには実際的な違いはありません。

最大の違いは、シングルトンがまだ特殊な静的専用Javaクラスとは対照的な通常のJava Beanであることです。このため、シングルトンはより多くの状況で受け入れられます。実際、これはデフォルトのSpring Frameworkのインスタンス化戦略です。消費者は、それが渡されたシングルトンであることを知っている場合も知らない場合もあり、通常のJava Beanのように扱います。要件が変更され、シングルトンが代わりにプロトタイプになる必要がある場合、Springでよく見られるように、コンシューマーにコードを変更することなく、完全にシームレスに実行できます。

他の誰かが、静的クラスは純粋に手続き型である必要があると前述しました(例:java.lang.Math)。私の考えでは、このようなクラスは渡されるべきではなく、属性としてstatic final以外のものを保持してはなりません。それ以外の場合は、シングルトンを使用してください。シングルトンの方がはるかに柔軟性があり、保守が容易です。


4

バックエンドに接続するDBフレームワークがあります。複数のユーザーにまたがるダーティリードを回避するために、シングルトンパターンを使用して、単一のインスタンスをいつでも使用できるようにしました。

C#では、静的クラスはインターフェイスを実装できません。単一のインスタンスクラスがビジネスコントラクトまたはIoCの目的でインターフェイスを実装する必要がある場合、ここで静的クラスなしのシングルトンパターンを使用します

シングルトンは、ステートレスシナリオで状態を維持する方法を提供します

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


3
  1. 遅延読み込み
  2. 個別の実装を提供できるように、インターフェースのサポート
  3. 派生型を返す機能(遅延読み込みとインターフェース実装の組み合わせとして)

ネストされた静的クラスは、Javaで非常に多くのインターフェースを実装できます。2番目のポイントは間違っています。
nanosoft 2016年

3

a。シリアル化-静的メンバーはクラスに属しているため、シリアル化できません。

b。コンストラクターをプライベートにしましたが、静的メンバー変数は引き続きサブクラスに渡されます。

c。すべてがクラスのロード時にのみロードされるため、遅延初期化を行うことはできません。


3

クライアントの観点からは、静的な動作はクライアントに知られていますが、シングルトンの動作はクライアントから隠して完了することができます。クライアントは、何度も何度も遊んでいるインスタンスが1つしかないことを知ることはありません。


3

私は以下を読み、それも理にかなっていると思います:

ビジネスの世話をして

最も重要なオブジェクト指向のルールの1つは、オブジェクトがそれ自体に責任があるということです。つまり、クラスのライフサイクルに関する問題は、静的などの言語構成に委譲するのではなく、クラスで処理する必要があります。

本のオブジェクト指向思考プロセス第4版から。


これは実際にクラスに責任を追加するだけなので、同意しません。これは(何かを実行すると仮定して)単一の責任の原則に違反していることを意味します。
ssmith

3

私が書いた記事では、シングルトンが静的クラスよりもはるかに優れている理由について私の見解を説明しました。

  1. 静的クラスは実際には標準的なクラスではありません–関数と変数を持つ名前空間です
  2. オブジェクト指向プログラミングの原則に違反するため、静的クラスの使用は良い習慣ではありません
  3. 静的クラスを他のパラメータとして渡すことはできません
  4. 静的クラスは「遅延」初期化には適していません
  5. 静的クラスの初期化と使用は常にハードトラッキングされます
  6. スレッド管理の実装は難しい

私は英語の文法のためにそれをブラッシュアップしますが、それ以外の場合、それは興味深い読み物です:)
Noctis '30 / 07/30

3
  1. シングルトンクラスのオブジェクトを作成してメソッドに渡すことができます。

  2. シングルトンクラスには継承の制限はありません。

  3. 静的クラスのオブジェクトを破棄することはできませんが、シングルトンクラスは破棄できます。


常に1つしかなく、その1つが常に静的参照を持っている場合、シングルトンをメソッドに渡すことの用途は何ですか?
アーロンフランケ

3

静的クラスとの区別

JDKには、シングルトンと静的の両方の例があり、一方でjava.lang.Mathは静的メソッドを持つ最後のクラスでjava.lang.Runtimeあり、他方ではシングルトンクラスです。

シングルトンの利点

  • シングルトンパターンよりも状態を維持する必要がある場合は、静的クラスよりも優れた選択肢です。静的クラスで状態を維持すると、特に並行環境でバグが発生するため、複数のスレッドによる適切な同期並列変更なしに競合状態が発生する可能性があります。

  • シングルトンクラスは、重いオブジェクトであれば遅延ロードできますが、静的クラスにはそのような利点はなく、常に積極的にロードされます。

  • シングルトンを使用すると、継承とポリモーフィズムを使用して基本クラスを拡張し、インターフェースを実装して、さまざまな実装を提供できます。

  • Javaの静的メソッドはオーバーライドできないため、柔軟性に欠けます。一方、シングルトンクラスで定義されたメソッドは、拡張することでオーバーライドできます。

静的クラスの欠点

  • シングルトンが期待されるときはいつでもモックオブジェクトを渡すことができるため、静的クラスよりもシングルトンの単体テストを書く方が簡単です。

静的クラスの利点

  • 静的メソッドはコンパイル時に結合されるため、静的クラスはシングルトンよりも優れたパフォーマンスを提供します。

シングルトンパターンの実現には、それぞれ長所と短所がいくつかあります。

  • 熱心な読み込みシングルトン
  • ダブルチェックロックシングルトン
  • 初期化オンデマンドホルダーイディオム
  • enumベースのシングルトン

それぞれの詳細な説明は冗長すぎるので、良い記事へのリンクを張るだけです - シングルトンについて知りたいすべてのこと


2

単一の静的クラスインスタンス(つまり、たまたま静的変数またはグローバル変数であるクラスの単一インスタンス)と、ヒープ上のクラスのインスタンスへの単一の静的ポインターとの間には、大きな違いがあります。

アプリケーションが終了すると、静的クラスインスタンスのデストラクタが呼び出されます。つまり、その静的インスタンスをシングルトンとして使用した場合、シングルトンは正しく機能しなくなります。そのシングルトンを使用するコードがまだ実行されている場合(たとえば、別のスレッドで)、そのコードはクラッシュする可能性があります。


1
では、アプリケーションが終了しても、シングルトンは引き続きメモリ内に残りますか?
nanosoft 2016年

アプリケーションではなく、現在のスレッドが終了したということですか?アプリケーションが終了した場合、別のスレッドがそこから何かを使用する方法はありません。
トム・ブリト、

2

私の頭の違いは、オブジェクト指向プログラミング(シングルトン/プロトタイプ)または関数型プログラミング(静的)の実装です。

注目すべきは、最終的にオブジェクトを保持することである場合、シングルトンパターンによって作成されたオブジェクトの数に焦点を合わせすぎています。他の人がすでに言ったように、それは拡張することができ、パラメータとして渡されますが、最も重要なことはそれはステートフルです。

一方、staticは関数型プログラミングの実装に使用されます。静的メンバーはクラスに属しています。彼らは無国籍です。

ところで、シングルトンスタティッククラスを作成できることをご存知でしたか:)


シングルトンは常にクラスに静的参照を持っているので、パラメーターとしてシングルトンを渡す意味は何ですか?
アーロンフランケ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.