静的クラスの代わりにシングルトンパターンを使用する必要があるのはいつですか?[閉まっている]


85

シングルトンクラスと静的クラスのどちらを使用するかを決定する際の設計上の考慮事項に名前を付けます。これを行う際に、あなたは2つを対比することを余儀なくされるので、あなたが思いつくことができるどんな対比もあなたの思考プロセスを示すのに役立ちます!また、すべてのインタビュアーは実例を見るのが好きです。:)


Javaクラスは、その内部クラスでない限り静的にすることはできません
Harshana 2015年

1
オブジェクトの状態が重要な場合はシングルトンを使用し、そうでない場合は静的クラスを使用します。
Levent Divilioglu 2015

回答:


80
  • シングルトンはインターフェイスを実装し、他のクラスから継承できます。
  • シングルトンは遅延ロードできます。実際に必要な場合のみ。初期化に高価なリソースの読み込みやデータベース接続が含まれている場合、これは非常に便利です。
  • シングルトンは実際のオブジェクトを提供します。
  • シングルトンは工場に拡張できます。舞台裏でのオブジェクト管理は抽象的であるため、保守が容易で、コードも改善されます。

2
また、このリンクを見てみましょう:codeofdoom.com/wordpress/2008/04/20/...
アミット

4
「シングルトンは遅延ロードできます」-C#では、静的コンストラクターは、静的メンバーが最初に参照されたときにのみ呼び出されます。PHPでは、自動読み込みを使用して、クラスが最初に使用されたときにのみ実行することができます。
mpen 2013年

Javaの静的初期化も怠惰です。そこにシングルトンのポイントはありません。
MikeFHay 2013

13

「両方を避ける」のはどうですか?シングルトンと静的クラス:

  • グローバルな状態を導入する可能性があります
  • 他の複数のクラスと緊密に結合する
  • 依存関係を隠す
  • ユニットテストクラスを分離することを困難にする可能性

代わりに、制御コンテナライブラリの依存性注入反転を調べてください。IoCライブラリのいくつかはあなたのために生涯管理を処理します。

(いつものように、静的数学クラスやC#拡張メソッドなどの例外があります。)


1
小さな問題:シングルトンクラスは依存性注入手法と互換性があります(依存性クラスに注入するだけで、何もハードコーディングする必要はありません)。これにより、モックとテストを分離して行うことができます。これらは、プラットフォーム全体が制限されていることがわかっているリソースを管理するための有効なデザインパターンでもあります。(典型的な例は、競合管理のないプリンターです。)
cdleary 2010年

@ cdleary-同意しました。ただし、従来の実装では、コードベース全体にSingleton.getInstance()が残ることがよくあります。リソースやキャッシュなどを管理するための「シングルトン」は、ライフタイム管理をサポートするPOCO / POJOおよびIoCコンテナフレームワークで実装できます(タイプをコンテナライフタイムとして登録すると、すべての解像度で同じインスタンスが取得されます)。
TrueWill 2010年

9
シングルトンに適切な埋葬を行いたい場合は、singletonfuneralservice.com
TrueWill 2010年

1
Hide Dependenciesこの点に関するちょっとした補足情報:たとえば、Ninjectを使用して、制御の反転パターンを実装できます。これにより、型にバインドすることで、型の1つのインスタンスのみを使用できますSingletonScope。つまり、常に同じインスタンスを注入しますが、クラスはシングルトンではありません。
LuckyLikey 2017年

8

唯一の違いは構文であると主張します:MySingleton.Current.Whatever()とMySingleton.Whatever()。デビッドが述べたように、状態はどちらの場合も最終的に「静的」です。


編集:埋葬旅団はdiggからやってきた...とにかく、私はシングルトンを必要とするケースを考えました。静的クラスは、基本クラスから継承することも、インターフェイスを実装することもできません(少なくとも.Netではできません)。したがって、この機能が必要な場合は、シングルトンを使用する必要があります。


7

この問題についての私のお気に入りの議論の1つはここにあります(元のサイトはダウンしていて、現在はInternet Archive Wayback Machineにリンクされています)。

シングルトンの柔軟性の利点を要約すると、次のようになります。

  • シングルトンは簡単に工場に変換できます
  • シングルトンは、さまざまなサブクラスを返すように簡単に変更できます
  • これにより、アプリケーションの保守性が向上します。

5

静的変数がたくさんある静的クラスはちょっとしたハックです。

/**
 * Grotty static semaphore
 **/
 public static class Ugly {

   private static int count;

   public synchronized static void increment(){
        count++;
   }

   public synchronized static void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized static boolean isClear(){
         return count==0;    

    }
   }

実際のインスタンスを持つシングルトンの方が優れています。

/**
 * Grotty static semaphore
 **/
 public static class LessUgly {
   private static LessUgly instance;

   private int count;

   private LessUgly(){
   }

   public static synchronized getInstance(){
     if( instance==null){
        instance = new LessUgly();
     }
     return instance;
   }
   public synchronized void increment(){
        count++;
   }

   public synchronized void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized boolean isClear(){
         return count==0;    

    }
   }

状態はインスタンス内でのみです。

したがって、シングルトンを後で変更して、プーリングやスレッドローカルインスタンスなどを実行できます。また、メリットを得るために、すでに記述されているコードを変更する必要はありません。

public static class LessUgly {
       private static Hashtable<String,LessUgly> session;
       private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
       private static final POOL_SIZE=5;
       private int count;

       private LessUgly(){
       }

       public static synchronized getInstance(){
         if( session==null){
            session = new Hashtable<String,LessUgly>(POOL_SIZE);
            for( int i=0; i < POOL_SIZE; i++){
               LessUgly instance = new LessUgly();  
               freePool.add( instance)
            }
         }
         LessUgly instance = session.get( Session.getSessionID());
         if( instance == null){
            instance = freePool.read();
         }
         if( instance==null){
             // TODO search sessions for expired ones. Return spares to the freePool. 
             //FIXME took too long to write example in blog editor.
         }
         return instance;
       }     

静的クラスで同様のことを行うことは可能ですが、間接ディスパッチでは呼び出しごとのオーバーヘッドが発生します。

インスタンスを取得して、引数として関数に渡すことができます。これにより、コードを「正しい」シングルトンに送ることができます。必要になるのは1つだけです...必要がなくなるまで。

大きな利点は、ステートフルシングルトンをスレッドセーフにすることができるのに対し、静的クラスは、シークレットシングルトンに変更しない限りできないことです。


4

シングルトンをサービスのように考えてください。これは、特定の機能セットを提供するオブジェクトです。例えば

ObjectFactory.getInstance().makeObject();

オブジェクトファクトリは、特定のサービスを実行するオブジェクトです。

対照的に、静的メソッドでいっぱいのクラスは、実行したいアクションのコレクションであり、関連するグループ(クラス)に編成されています。例えば

StringUtils.reverseString("Hello");
StringUtils.concat("Hello", "World");

ここでのStringUtilsの例は、どこにでも適用できる機能のコレクションです。シングルトンファクトリオブジェクトは、必要に応じて作成および渡すことができる明確な責任を持つ特定のタイプのオブジェクトです。


4

静的クラスは実行時にインスタンス化されます。これには時間がかかる可能性があります。シングルトンは、必要な場合にのみインスタンス化できます。


13
シングルトンは実行時にもインスタンス化されます
再帰的

1
@recursive:シングルトンのインスタンス化を制御できます。
Nikit Batale 2010年

3
おそらくより良い言葉は(インスタンス化ではなく)初期化でしょう
Marlon

3

シングルトンは、静的クラスと同じように使用しないでください。本質的に、

MyStaticClass.GetInstance().DoSomething();

本質的にと同じです

MyStaticClass.DoSomething();

実際に行うべきことは、シングルトンを単なる別のオブジェクトとして扱うことです。サービスがシングルトンタイプのインスタンスを必要とする場合は、そのインスタンスをコンストラクターに渡します。

var svc = new MyComplexServce(MyStaticClass.GetInstance());

サービスは、オブジェクトがシングルトンであることを認識してはならず、オブジェクトを単なるオブジェクトとして扱う必要があります。

オブジェクトは、実装の詳細として、および全体的な構成の側面として、物事を容易にする場合はシングルトンとして確実に実装できます。ただし、オブジェクトを使用するものは、オブジェクトがシングルトンであるかどうかを知る必要はありません。


2

「静的クラス」とは、静的変数のみを持つクラスを意味する場合、実際には状態を維持できます。私の理解では、唯一の違いは、このことにアクセスする方法です。例えば:

MySingleton().getInstance().doSomething();

MySingleton.doSomething();

MySingletonの内部は明らかにそれらの間で異なりますが、スレッドセーフの問題は別として、どちらもクライアントコードに関して同じように動作します。


2
シングルトンはそれ自体がオブジェクトです->引数として渡すことができます。
クリスチャンクラウザー

2

シングルトンパターンは通常、複数のスレッドが同時にデータにアクセスできるインスタンスに依存しないデータまたは静的データを処理するために使用されます。一例として、状態コードがあります。


1

シングルトンは絶対に使用しないでください(可変状態のないクラスをシングルトンと見なさない限り)。「静的クラス」は、おそらくスレッドセーフなキャッシュなどを除いて、変更可能な状態であってはなりません。

シングルトンのほとんどすべての例は、それを行わない方法を示しています。


4
ハードウェアリソースを制御するマネージャークラスはどうですか?ログファイルクラスはどうですか?
RJFalconer 2009

0

シングルトンが処分できるものである場合、その後クリーンアップするために、それが限られたリソース(つまり、1つだけ)であり、常に必要ではなく、何らかのメモリがある場合、または割り当てられたときのリソースコスト。

静的状態フィールドを含む静的クラスとは対照的に、シングルトンがある場合、クリーンアップコードはより自然に見えます。

ただし、コードはどちらの方法でも同じように見えるので、質問するより具体的な理由がある場合は、おそらく詳しく説明する必要があります。


0

この2つは非常に似ている可能性がありますが、真のシングルトン自体をインスタンス化(1回付与)してから提供する必要があることに注意してください。のインスタンスを返すPHPデータベースクラスmysqliは、静的メンバーとしてインスタンスを持つクラスのインスタンスではなく、別のクラスのインスタンスを返すため、実際にはシングルトンはありません(一部の人はそれを呼んでいます)。

したがって、コード内で1つのインスタンスのみを許可する予定の新しいクラスを作成する場合は、シングルトンとして作成することをお勧めします。プレーンジェーンクラスを作成し、それに追加して単一インスタンス化の要件を容易にすることと考えてください。(のようにmysqli)変更できない他の誰かのクラスを使用している場合は、静的クラスを使用する必要があります(定義の前にキーワードを付けなかった場合でも)。


0

シングルトンはより柔軟性があり、インスタンスメソッドが特定のコンテキストに基づいてシングルトンのタイプの異なる具象サブクラスを返す場合に役立ちます。


0

静的クラスを引数として渡すことはできません。シングルトンのインスタンスは可能です。他の回答で述べたように、静的クラスのスレッドの問題に注意してください。

rp


0

シングルトンにはコンストラクタとデストラクタがあります。言語によっては、コンストラクターは、シングルトンが最初に使用されたときに自動的に呼び出される場合と、シングルトンがまったく使用されていない場合は呼び出されない場合があります。静的クラスには、そのような自動初期化はありません。

シングルトンオブジェクトへの参照が取得されると、他のオブジェクトと同じように使用できます。シングルトンへの参照が以前に保存されている場合、クライアントコードはシングルトンの使用を知る必要さえないかもしれません:

Foo foo = Foo.getInstance();
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton

これにより、IoCのような実際のパターンを優先してシングルトンパターンを捨てることを選択した場合、明らかに物事が簡単になります。


0

ルックアップテーブルのように、可能であればコンパイル時に計算するものを実行時に計算する必要がある場合は、シングルトンパターンを使用します。


0

シングルトンが静的クラスよりも理にかなっているのは、コストのかかるリソース(データベース接続など)のプールを構築する必要がある場合だと思います。誰もプールを使用しない場合は、プールの作成に関心がありません(静的クラスは、クラスがロードされたときにコストのかかる作業を行うことを意味します)。


0

データの効率的なキャッシュを強制したい場合は、シングルトンも良い考えです。たとえば、xmlドキュメントで定義を検索するクラスがあります。ドキュメントの解析には時間がかかる可能性があるため、定義のキャッシュを設定しました(outOfmemeoryErrorsを回避するためにSoftReferencesを使用しています)。目的の定義がキャッシュにない場合は、高価なxml解析を行います。それ以外の場合は、キャッシュからコピーを返します。複数のキャッシュがあると、同じ定義を複数回ロードする必要がある可能性があるため、静的キャッシュが必要です。通常の(非静的)データメンバーのみを使用してクラスを記述できるように、このクラスをシングルトンとして実装することを選択します。これにより、何らかの理由(シリアル化、単体テストなど)で必要になった場合でも、クラスのインスタンス化を作成できます。


0

すでに述べたように、シングルトンはサービスのようなものです。Proはその柔軟性です。静的、まあ、シングルトンを実装するにはいくつかの静的パーツが必要です。

Singletonには、実際のオブジェクトのインスタンス化を処理するコードがあります。これは、レースの問題が発生した場合に非常に役立ちます。静的ソリューションでは、複数のコード位置でのレースの問題に対処する必要がある場合があります。

ただし、いくつかの静的変数を使用してシングルトンを構築できるのと同じように、「goto」と比較できる場合があります。他の構造を構築するのに非常に便利ですが、実際にはその使用方法を知る必要があり、「使いすぎ」てはなりません。したがって、一般的な推奨事項は、シングルトンに固執し、必要に応じて静的を使用することです。

他の投稿も確認してください:シングルトン実装ではなく静的クラスを選択するのはなぜですか?


0

参照 これを

概要:

a。従うことができる簡単な経験則の1つは、状態を維持する必要がない場合は静的クラスを使用でき、そうでない場合はシングルトンを使用する必要があります。

b。シングルトンを使用するのは、それが特に「重い」オブジェクトである場合です。オブジェクトが大きく、適度な量のメモリを使用している場合は、多くのn / w呼び出し(接続プール)などがあります。複数回インスタンス化されないようにするため。シングルトンクラスは、このようなケースが発生するのを防ぐのに役立ちます


-1

単一のクラスに状態が必要な場合。シングルトンはグローバル状態を維持しますが、静的クラスは維持しません。

たとえば、レジ​​ストリクラスの周りにヘルパーを作成します。変更可能なハイブ(HKey現在のユーザーとHKEYローカルマシン)がある場合は、次のようになります。

RegistryEditor editor = RegistryEditor.GetInstance();
editor.Hive = LocalMachine

これで、そのシングルトンへのそれ以上の呼び出しは、ローカルマシンハイブで動作します。それ以外の場合は、静的クラスを使用して、ローカルマシンがeverytiemをハイブするように指定するか、のようなメソッドを使用する必要がありますReadSubkeyFromLocalMachine


1
私はこのようにシングルトンを使用することに反対します...次の呼び出し元がハイブの設定を忘れて、間違ったハイブのレジストリに書き込む可能性があるため、状態を長引かせ続けることは非常に危険です... :-(これはおそらく人々はシングルトンが悪いと思わせる誤用の例を。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.