私は自分のWebサイトのユーザーに関する情報を格納するデータベースを作成しています(私はstuts2を使用しているため、Java EEテクノロジ)。データベースについては、DBManagerを作成します。シングルトンを適用する必要がありますここでパターン化するか、それともすべてのメソッドを静的にしますか?
このDBManagerは、ユーザープロファイルの追加、削除、更新などの基本的なものに使用します。それに加えて、他のすべてのクエリの目的で使用します。たとえば、ユーザー名がすでに存在するかどうかを確認したり、管理目的などですべてのユーザーを取得したりします。
私の質問
追伸データベースはこれよりも大きいです。ここでは、ユーザー情報の保存に使用するテーブルについてのみ説明します。
なぜシングルトンと静的メソッドが唯一の選択肢なのですか?
私の観点からは、どちらのオプションもかなり悪いです。 Singleton AntiPattern を読んでください。シングルトンパターンのほとんどの使用例は正しくありません。
あなたの場合、私はインスタンスオブジェクトを使用し、依存関係注入(DIフレームワークを使用している場合)または Service locator/Registry pattern を使用します。
シングルトンクラスを使用すると、作成されるオブジェクトの管理方法をより詳細に制御できます。
まず、シングルトンはオブジェクトです。静的メソッドはオブジェクトのインスタンスを返し、単一のインスタンスのみ、または必要に応じて複数のインスタンスを作成できます。
シングルトンも遅延ロードされます。つまり、シングルトンは最初に呼び出されるまでインスタンス化されません。
シングルトンは静的メソッドを使用しないため、非静的コンテキストでシングルトンを使用しても問題はありません。
シングルトンは拡張/サブクラス化できます。
それらはオブジェクトであるため、他のオブジェクトに注入できます。これにより、依存性注入の概念を利用して優れたデザインパターンを作成できます。たとえば、これはSpring Bean IoC(制御依存性注入の反転)モデルのしくみです。
どちらも理想的ではありませんが、特に静力学の束ではありません。これが私の経験からの実際の例です。データベースと話しました。誰もが「1つしかない」と言ったので、誰かがSpringによって構成された標準のシングルトンを使用しました。次に、新しい要件が追加されました。データをanother(remote)データベースにコピーできるようにするためです。おっとっと。 DBを表す実際のオブジェクトがあり、これは「ほとんど使用されない」機能だったので、一時コピーを作成してフィールドと値を変更することでハックすることができましたが、これをグローバルスタティックで実装すると、実際の災害。
私の経験では、「彼ら」が1つだけのDB、1人のユーザー、1つのアプリケーション、1つのメインウィンドウなどがあると言う場合、「彼ら」は間違っています。 Singltonを使用すると、少なくともリファクタリングして修正するチャンス。
オールスタティック方式とシングルトンパターンの適用の違いは何ですか?
どちらも同じ効果があります。メソッドを含むクラスのインスタンスを取得する方法を気にせずにクラスメソッドを呼び出すことができます。
ただし、Unittestingの静的メソッドを実装する場合、静的メソッドを簡単に作成することができないため、問題が多くなります mocked 。
テストの観点からは、singeltonを使用してモックでユニットテストできるようにするコードを書き換える方が簡単です。
最も柔軟な解決策は、 Dependency_injection を使用することです(@ Tazzy531で推奨されているように)di-container-frameworkを使用している場合、またはコードによって依存関係をワイヤリングしている場合。
これが主な質問の答えになることを願っています。
SOにはすでにいくつかの素晴らしい答えがあります 。引用します。
Heinzi によるベストアンサー:
シングルトンは、ある種のグローバル状態をアプリケーションに導入するために使用されます。ステートレスである場合、シングルトンを使用する意味もわかりません。
- あなたは予見可能な将来の状態でそれを拡張すると予想します
- ある特定のtechnical理由のためにobject instanceが必要です(たとえば、 C#
SyncLock
ステートメントの場合、これはすでにかなり先に進んでいますが)または- 継承が必要です。つまり、同じインターフェースを使用するが実装が異なるシングルトンを別のシングルトンに簡単に置き換えることができるようにしたい場合です。たとえば、Javaの
Toolkit.getDefaultToolkit()
メソッドは、正確な型がシステムに依存するシングルトンを返します。
back2dos による関連性の高いコメント:
(...)シングルトンは、グローバルな状態を導入するために誤用されています。シングルトンの目的は、オブジェクトをグローバルに使用可能にすることではなく、オブジェクトが1回だけインスタンス化されるようにすることです。グローバルオブジェクトは必要悪です。本当に必要な場合を除いて、SomeSingleton.getInstance()。someMethod()がいたるところにあるため、一般的に高結合につながるため、それらを使用しないようにしてください。
tzaman も良い答えを書いています:
静的メソッドクラスの代わりにステートレスシングルトンが使用されるケース、つまり Dependency Injection のケースを見ることができました。
直接使用しているユーティリティ関数のヘルパークラスがある場合、非表示の依存関係が作成されます。誰がどこで使用できるかは制御できません。ステートレスシングルトンインスタンスを介して同じヘルパークラスを注入すると、使用される場所と方法を制御し、必要に応じてそれを置き換える/モックする/などができます。
これをシングルトンインスタンスにすることで、必要以上のタイプのオブジェクトが割り当てられないことが保証されます(必要になるのは1つだけなので)。
そして最後に Sebastien もかなりよく答えました:
実際、私はここで言及されていない別の答えを見つけました:静的メソッドはテストするのが難しいです。
ほとんどのテストフレームワークはインスタンスメソッドのモックに最適ですが、それらの多くは静的メソッドのモックを適切に処理していません。
そうは言っても、私は Toolbox pattern を使用することをお勧めします。