シングルトンおよび静的クラスのケーススタディ

シングルトンクラスと静的クラスの違いは何ですか? しかし、違いを知って、私はまだ私が選ぶ必要があるときはいつも混乱していると感じます。

私自身は、2つの異なるケースを定義しました。私は、このクラスのインスタンスが1つだけ(非常にまれです)でなければならないPOJOクラス(Javaの場合)と、すべてのサービスクラスの静的クラス)。

たとえば、私のアプリケーションでは、メッセージを保存する必要があります(シリアライズ可能なクラスのMessageを持っています)、ファイルに書き込んだり、ファイルから読み込んだり、ランタイム中にアクセスしたりする必要があります。ここでシングルトンを使用する理由はありません。静的クラスは大丈夫です。静的な唯一のクラスは、read、write、getMessagesの3つの機能を持つMessageStorageと、メッセージの静的なprivate arraylistです。

このアプローチは妥当かどうか、もしそうでなければ、その問題は何か?

2
だからこのメッセージの場合、あなたは何をしますか?
追加された 著者 Sergey,
グローバルな状態/静的状態は一般的に悪い形であると考えられます。そのため、シングルトンはしばしば反パターン。 "良い習慣"は、静的クラスとシングルトンは、状態のないヘルパーメソッド(例: Math.sqrt(4))でのみ使用されるべきであるということです。
追加された 著者 Bringer128,
格納された状態が必要な場合は、オブジェクトへの参照を1つだけ持つことになります。それはシングルトンパターンでは保証されませんが、情報を必要とするものによってグローバルに到達可能な場所に存在します。それは同じ効果を達成するだろうが、私のポストで述べたように、違いはスケーラビリティであり、変更可能性は要求の変化に対応して改善される。クラスを作成するとシングルトンのゴールが達成されます。あなたがする必要があるのは、世界的に見つかる場所での参照です。
追加された 著者 Dessus,
単体テストの場合(静的メソッドが迷惑な理由を示すのに役立ちます)、簡単ではないことに気づくでしょうか?静的メソッドをテストするための模擬テスト。単体テストが妨げられている場合(たとえあなたがそれに興味がないとしても)、あなたのコードは堅牢ではなく、要件の変更をうまく処理できません。
追加された 著者 Dessus,

3 答え

Javaで「シングルトン」を使用する主な理由は2つあります。

1)したがって、一部のストレージは、それ以外の場合は「静的」クラスと関連付けることができます。

2)与えられたサービスの異なるサブクラス(またはインタフェース実装)に対して複数の "シングルトン"を持つことができ、シングルトンは、使用する特定のサービスを識別する方法として渡されます。

もちろん、#1の代わりに静的なクラスの静的フィールドを使用してデータを格納することもできますが、サブジェクトクラスの1つのインスタンスにそのクラスを格納する方が便利な場合があります(多くの場合、効率的です)。データ、他のクラスのインスタンスである複数の静的メンバー。

そして、re#2では、JDKには、1つのクラスが複数の「シングルトン」を実装している場合が多く、「定数」を定義していると考えられます。 (例えば、java.awt.font.TextAttribute。)

一般に、Javaは真のクラス関連(およびクラス保護された)静的データを実装しているので、シングルトンを持つ動機はJavaベースの言語よりもJavaベースではあまりありません(まったく偽装されている場合) C言語であるため、クラス内に複数の静的フィールドを持つことができ、C言語のフィールドを格納するための「中央」オブジェクトを持つ必要があります。

1
追加された

理想的なデザイン:-)

  • MessageStoreはインターフェースでなければなりません
  • MessageStoreFactoryは、getMessageStore()メソッドを持つシングルトンでなければなりません(getMessageStore()が毎回同じメッセージストアを返す場合、問題はなく、シングルトンもあります)。
  • 次に、FileMessageStore、JDBCMessageStore、SubversionMessageStoreなどの複数のMessageStore実装を持つことができます。
  • 最も重要なのは、MockMessageStoreを使用してメッセージストアをモックアウトし、メッセージストアとは独立したメッセージストアに依存するコンポーネントをテストできることです。たとえば、MessageViewをテストしてエラーが発生した場合、MockMessageStoreが正しければ、エラーがMessageViewにあり、静的MessageStoreではないことを確認できます。

それはクールな子供たちが今のところ何とかしていることです。とにかく...工場ではなく依存症注入ですが、一歩一歩...

1
追加された
依存性注入+1
追加された 著者 Dessus,

ここで本当に理解できるのは、c#/ javaにはさまざまなメモリグループがあるということです。

すべてのクラスは、クラスローダーメモリと呼ばれるメモリセクションにロードされます。静的なものを作ると、それはクラスローダーのメモリに残ります。そこから使用できますが、1つのインスタンスしか持てません。クラスローダーメモリ用のガベージコレクタはありません。アプリケーションの存続期間中、すべてがそこにとどまります。

シングルトンであろうとなかろうと、クラスのインスタンスを作成することは、メモリコピーが完了したことを意味し、クラスローダーメモリからクラスをコピーし、インスタンスが格納されている領域にコピーします。インスタンスはガベージコレクションできます。

シングルトンと静的クラスのオプションの間の実際の決定ポイントは次のとおりです。

1)継承が必要か、クラスのインターフェースが必要ですか(シングルトンが必要な場合)
2)あなたのクラスがアプリケーションと同じライフサイクルを持つように強制するのは意味がありますか?(つまり、クラスを手動でクリアするか、コードを無意識的に増加させてメンテナンス性を低下させるメソッドを作成する必要があります。 (あなたがシングルトンを望んでいない場合)
3)アプリケーションにスケーラビリティと変更の可能性が必要ですか?現在のところ、シングルトンはアンチ・パターンとみなされ、IFは静的なプロパティを介して実装されます。この理由は、単一ウィンドウアプリケーションが突然マルチウィンドウになり、コードを書き直す必要があるため、クラスに静的インスタンスプロパティを公開するなどのインフラストラクチャに投資することです。 (コードの書き換えは、特にコアインフラストラクチャの場合には、悪い設計を示しています)。

一般的な経験則として、私は以下を推奨します:

  • クラスワイド変数があるクラス。シングルトンでなければなりません(潜在的にスケールアウトする必要があるため)。
  • 各メソッドが独立しているクラスは静的でなければなりません。
1
追加された