web-dev-qa-db-ja.com

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

静的クラスとシングルトンパターンの間には、どんな本当の(すなわち実用的な)違いがありますか?

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

1629
Jorge Córdoba

シングルトンメソッドとスタティックメソッドのどちらもスレッドセーフではないと言う理由は何ですか?通常、両方の はスレッドセーフであるように 実装されるべきです。

シングルトンと多数の静的メソッドの大きな違いは、シングルトンはインターフェースを実装できる(または私の経験ではあまり一般的ではありませんが、役に立つ基本クラスから派生する)ことができるということです。 "実装。

1142
Jon Skeet

真の答えはJon Skeetによるものです。 ここで別のフォーラムに参加しています

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

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

437
Kezzer
  1. シングルトンオブジェクトは Heap に格納されますが、静的オブジェクトは stack に格納されます。
  2. シングルトンオブジェクトを clone (デザイナが許可しない場合)することはできますが、静的クラスオブジェクトを複製することはできません。
  3. シングルトンクラスは _ oop _ (オブジェクト指向の原則)に従いますが、静的クラスは従いません。
  4. シングルトンクラスを使ってinterfaceを実装することはできますが、クラスの静的メソッド(またはC#static classなど)は実装できません。
342
Vadluri Sreenu

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

136
neil.johnson

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

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

staticsingletonの間で選択するための私のルール:

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

62
Xaqron

静的クラス: - /

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

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

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

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

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

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

  7. より良いパフォーマンス(静的メソッドはコンパイル時に結び付けられます)

シングルトン: - /

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

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

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

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

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

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

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

  8. 必要に応じて遅延ロードすることができます(静的クラスは常にロードされます)。

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

54
RajeshVerma

静的クラスは静的メソッドのみを持つクラスであり、そのためのWordは「関数」になります。静的クラスで具体化されたデザインスタイルは、純粋に手続き型です。

一方、SingletonはOO designに固有のパターンです。それは、オブジェクトのインスタンスであり(多相など、その固有の可能性はすべてあります)、その特定の役割のインスタンスがその存続期間全体にわたって1つだけ存在することを保証する作成手順を持ちます。

49
Morendil

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

簡単な例:

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

Jon Skeet's Answer に展開するには/ /

シングルトンと多くの静的メソッドの大きな違いは、シングルトンはインターフェースを実装できる(またはあまり一般的ではありませんが、便利な基本クラスから派生できる)ことです。

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

24
Mike Rylander

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

21
Alex

これは良い記事です: 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メソッドを保持するためには静的クラスを使用し、それ以外のすべてにはSingletonを使用します。


編集

19
JackDev

私は偉大なOO理論家ではありませんが、私が知っていることから、シングルトンと比較して静的クラスに欠けている唯一のOO機能は多態性です。あなたがそれを必要としないのであれば、静的クラスではもちろん継承(インターフェースの実装についてはわからない)やデータと関数のカプセル化を持つことができます。

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

編集:
もう1つの違いは、スタティッククラスはプログラムの開始時に インスタンス化 され、プログラムの有効期間全体にわたって存続しますが、シングルトンはある時点で明示的にインスタンス化されるということです。破壊することもできます。

*または言語によっては、最初の使用時にインスタンス化されることもあります。

17
Petruza

Loggerが静的クラスであった場合、Jonのポイントを説明するために以下に示すことはできません。クラスSomeClassILogger実装のインスタンスがそのコンストラクタに渡されることを期待しています。

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

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();
    }
}
15
developer747

シングルトンはISがインスタンス化した通常のクラスですが、クライアントコードから間接的に1回だけです。静的クラスはインスタンス化されません。私が知っている限りでは、静的メソッド(静的クラスは静的メソッドを持たなければならない)は非静的よりも高速です。

編集する
FxCopパフォーマンスルールの説明: "インスタンスデータにアクセスしたり、インスタンスメソッドを呼び出したりしないメソッドは、静的(VBでは共有)としてマークできます。そうすると、コンパイラはこれらのメンバーに非仮想呼び出しサイトを発行します。現在のオブジェクトポインタがnullではないことを保証する呼び出しごとに実行時にチェックを行わないようにすると、パフォーマンスに敏感なコードのパフォーマンスが大幅に向上する可能性があります。 "
これが静的クラスの静的メソッドにも当てはまるかどうかは実際にはわかりません。

11
agnieszka

Singletonはインスタンス化されています。インスタンス化されたインスタンスは1つだけなので、Singletonでは single になります。

静的クラスは、それ自身以外のものによってインスタンス化することはできません。

9
Kezzer

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

single 」という単語は、アプリケーションのライフサイクル全体で単一のオブジェクトを意味するため、適用範囲はアプリケーションレベルです。

static にはObjectポインタがないため、有効範囲はApp Domainレベルです。

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

あなたはについての他の興味深い違いを見つけることができます。 シングルトンパターンとスタティッククラス

6

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

以下の例では、これを説明します。メソッド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()をモックするのは困難でした。あなたはパワーモックで静的にモックすることができました、しかしすべての製品がそれを使うことができるというわけではありません。

6
Amir Bareket

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

  • シングルトンはインスタンス/オブジェクトを持ち、静的クラスは静的メソッドの集まりです。
  • シングルトンは拡張することができます。静的クラスはできませんが、インターフェイスを介して。
  • SOLIDの原則で開閉の原則をサポートするシングルトンは継承できますが、静的クラスは継承できないため、変更する必要があります。
  • インスタンスを持たない静的クラスはパラメータとして渡すことができませんが、シングルトンオブジェクトはメソッドに渡すことができます
5
Faran Shabbir

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

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

5

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

C#では、静的クラスはインタフェースを実装できません。単一のインスタンスクラスが業務契約またはIoCの目的でインタフェースを実装する必要がある場合は、ここで静的クラスなしでSingletonパターンを使用します。

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

あなたに役立つことを願っています..

4
RK_Muddala

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

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

他の誰かが、静的クラスは純粋に手続き型であるべきだと先に述べました。 Java.lang.Math。私の考えでは、そのようなクラスは決して渡されるべきではなく、静的なfinal以外のものを属性として持つべきではありません。それ以外のすべてについては、シングルトンを使用してください。シングルトンのほうがはるかに柔軟で保守が簡単です。

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

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

ビジネスの世話をして

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

本反対論の思想プロセス第4版から。

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

  1. 静的クラスは実際には正規クラスではありません - それは関数と変数を持つ名前空間です
  2. オブジェクト指向プログラミングの原則に違反するため、静的クラスを使用することはお勧めできません。
  3. 静的クラスを他のクラスのパラメータとして渡すことはできません
  4. 静的クラスは「遅延」初期化には適していません
  5. 静的クラスの初期化と使用は常に困難です
  6. スレッド管理の実装は難しい
3
user2604650
  1. シングルトンクラスのオブジェクトを作成してmethodに渡すことができます。

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

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

3
Sanjay Dwivedi

a。直列化 - 静的メンバーはそのクラスに属しているため、直列化できません。

b。コンストラクターを非公開にしましたが、静的メンバー変数は依然としてサブクラスに渡されます。

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

3
Vivek Vermani

クライアントの観点からは、静的な振る舞いはクライアントに知られていますが、シングルトンの振る舞いはクライアントから隠されて完了することができます。クライアントは、彼が何度も何度もプレイしているインスタンスが1つしかないことを決して知っていないかもしれません。

3

単一の静的クラス instance(つまり、静的変数または大域変数であるクラスの単一インスタンス)と 単一の静的ポインタ ヒープ上のクラス:

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

2
gnasher729

Javaの static class には静的メソッドしかありません。それは機能のコンテナです。それは手続き型プログラミング設計に基づいて作成されています。

シングルトンクラス はオブジェクト指向設計のパターンです。 Singletonクラスは、JVM内のオブジェクトのインスタンスを1つだけ持ちます。このパターンは、JVMにそのクラスのインスタンスが常に1つだけ存在するように実装されています。

1
Premraj

フル機能のクラスが欲しいときメソッドや変数はたくさんありますが、シングルトンを使用します。

1つか2つのメソッドしか持たないクラスが必要な場合は、 MailServiceクラスには、SendMail()というメソッドが1つだけあります。静的クラスとメソッドを使用します。

1
Lev

私の頭の違いは、オブジェクト指向プログラミング(Singleton/Prototype)または関数型プログラミング(Static)の実装です。

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

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

ところで、シングルトンの静的クラスを作成できることを知っていましたか:)

1
Atif Karbelkar

静的クラスと非静的シングルトンクラスの違いを理解したように、静的はC#ではインスタンス化されていない「型」であり、シングルトンは真の「オブジェクト」です。つまり、静的クラスのすべての静的メンバーはその型に割り当てられますが、Singletonではオブジェクトの下に格納されます。ただし、静的クラスは構造型のような値型ではないため、参照型のように動作します。

つまり、シングルトンを作成すると、クラス自体は静的ではありませんが、そのメンバは静的なので、自分自身を参照するシングルトン内の静的メンバは、それ自体の中空の「型」ではなく実際の「オブジェクト」に関連付けられます。そのような種類のものは、静的シングルトンと非静的シングルトンの他の機能とメモリ使用量を超えた違いを明確にしています。

どちらもメンバーの単一コピーである静的メンバーを使用しますが、シングルトンは静的メンバーに加えてアドレスが存在する実際のインスタンス化された「オブジェクト」を囲むように参照メンバーをラップします。そのオブジェクト自体はinを受け渡して参照することができ、値を追加することができるという特性を持っています。 Staticクラスは単なる型なので、その静的メンバを指す以外には存在しません。その概念の種類は、継承やその他の問題を超えて、シングルトン対スタティッククラスの目的を固めました。

1
Stokely

静的クラスの例

public class Any {

    private static Any instance = new Any();

    private Singleton() {
        System.out.println("creating");
    }
}

シングルトンパターンの場合は1つのインスタンスしか存在しません。

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
        System.out.println("creating");
        if (instance != null) {
            throw new RuntimeException("Imposible create a new instance ");
        }
    }
}
0
x-rw