回答:
Googleテストのブログは(テスト可能なコードを作成するために)シングルトンを避けることについて一連のエントリがあります。多分これはあなたを助けることができます:
最後の記事では、新しいオブジェクトの作成をファクトリーに移動する方法を詳細に説明しているため、シングルトンの使用を回避できます。確かに読む価値があります。
つまり、すべての新しいオペレーターを工場に移動します。寿命が近いオブジェクトをすべて1つのファクトリにグループ化します。
最善の方法は、代わりにFactoryパターンを使用することです。(ファクトリで)クラスの新しいインスタンスを構築するとき、単一のインスタンス(ファクトリクラスに格納する)への参照として、または関連する新しいオブジェクトへのデータ。
すべてのオブジェクトには、シングルトンでの使用に使用されていたデータが含まれます。全体的に大きな違いはないと思いますが、コードを読みやすくすることができます。
Spring Frameworkを使用している場合は、通常のBeanを作成できます。デフォルトでは(または明示的に設定した場合scope="singleton"
)、Beanのインスタンスが1つだけ作成され、そのインスタンスは、Beanが依存関係で使用されるか、を介して取得されるたびに返されますgetBean()
。
シングルトンパターンを結合しなくても、単一インスタンスの利点が得られます。
理解が難しく、壊れやすい非常に大きなオブジェクトで終了するため、単一の構成オブジェクトに対する責任を積み重ねないでください。
たとえば、特定のクラスに別のパラメータが必要な場合は、Configuration
オブジェクトを変更し、それを使用するすべてのクラスを再コンパイルします。これはやや問題があります。
共通のグローバルで大きなConfiguration
オブジェクトを回避するために、コードをリファクタリングしてみてください。必要なパラメーターのみをクライアントクラスに渡します。
class Server {
int port;
Server(Configuration config) {
this.port = config.getServerPort();
}
}
次のようにリファクタリングする必要があります:
class Server {
public Server(int port) {
this.port = port;
}
}
ここでは、依存性注入フレームワークが役立ちますが、厳密には必須ではありません。
静的メソッドを使用して、シングルトンと同じ動作を実現できます。Steve yeggeがこの投稿で非常によく説明しています。
静的なメソッドとフィールドのみを含むクラスは可能ですか?私はあなたの状況が正確に何であるかわかりませんが、調査する価値があるかもしれません。
あまりきれいではないかもしれませんが、変更したい情報ビットをシングルトンを作成するメソッドに渡すことができます-を使用する代わりに
public static Singleton getInstance() {
if(singleton != null)
createSingleton();
return singleton;
}
}
createSingleton(Information info)
アプリケーションの起動時に(および単体テストのsetUp-Methodsで)直接呼び出すことができます。
シングルトンは悪ではありませんが、デザインパターンに欠陥があります。実行時にそのインスタンスを1つだけ作成したいが、ユニットテスト中に複数の分離されたインスタンスを作成して確定的な結果を保証したいクラスがあります。
Springなどを使用したDIは非常に優れたオプションですが、唯一のオプションではありません。