クラスが内部的に1つ以上のリソースに依存し、そのリソースがクラスの動作に影響を与える場合、シングルトンと静的ユーティリティクラスは使用しない方が良いでしょう。
これらのリソースをクラス自体で作成するのではなく、必要なリソースをコンストラクタに渡す方が望ましいです。依存性の注入を通じて、クラスの柔軟性、再利用性、テストの容易性を向上させることができます。
例
静的ユーティリティクラスを使用した例
このユーティリティクラスは、辞書を1つだけ使用すると想定しています。しかし、実際には、辞書は言語ごとに別々に存在し、さらには特殊な語彙用の辞書を別途用意する場合もあります。
シングルトンパターンを使用した例
シングルトンパターンを使用した場合も、同様に辞書を1つだけ使用すると想定しているため、上記と同じ欠点が発生します。
解決策1 - フィールドからfinalキーワードを削除する
静的ユーティリティクラスまたはシングルトンパターンで、dictionaryに対してfinalキーワードを削除し、外部からdictionaryを別の辞書に置き換えられるように設計することもできます。しかし、この方法は使い勝手が悪く、マルチスレッド環境では同時実行性の問題を引き起こす可能性があります。
解決策2 - 依存性の注入を使用する
静的クラスとシングルトンパターンは、内部的なリソースに依存すべきではないという事実を、上記の例を通して理解することができました。つまり、内部リソースは外部から注入される方が望ましいということです。
依存性の注入を使用したクラスは、finalキーワードのおかげで不変性を保証することができ、複数のリソースインスタンスをサポートするという利点があります。また、依存性の注入は、コンストラクタだけでなく、静的ファクトリやビルダーでも適用可能です。
依存性の注入では、単純にリソース自体を渡す方法もありますが、リソースファクトリを渡す方法もよく使用されます。ファクトリとは、呼び出されるたびに特定の型のインスタンスを繰り返し作成するオブジェクトのことです。このような方法はファクトリメソッドパターンと呼ばれ、Java 8ではSupplier<T>がファクトリを表す完璧な例です。
主に限定的なワイルドカード型を使用して、ファクトリの型パラメータを制限します。この方法を使用すると、クライアントは、自分が指定した型のサブタイプであれば、どのようなものでもファクトリを渡すことができるようになります。
依存性の注入は柔軟性とテストの容易性を向上させますが、依存関係が非常に多いプロジェクトでは、コストがかかる場合があります。このような場合、依存性注入フレームワーク(Dagger、Guice、Springなど)を使用してコストを削減することができます。
コメント0