シングルトンが静的クラスより実際に簡単または優れているのはいつですか?シングルトンを作成することは、実際には必要ではない余分な労力であるように思えますが、それには十分な理由があると確信しています。そうでなければ、明らかに、それらは使用されません。
静的クラスよりもシングルトンを優先する1つの理由は(自由に使えるより良いパターンがないと仮定して;))、あるシングルトンインスタンスを別のインスタンスと交換することです。
たとえば、次のようなロギングクラスがあるとします。
public static class Logger {
public static void Log(string s) { ... }
}
public class Client {
public void DoSomething() {
Logger.Log("DoSomething called");
}
}
これは本当にうまくいきますが、ロガーがデータベースに何かを書き込んだり、コンソールに出力を書き込んだりするとどうなりますか。テストを作成している場合、おそらくこれらすべての副作用を望まないでしょう。しかし、logメソッドは静的なので、それ以外は何もできません。
さて、テストのためにLogメソッドをホットスワップしたいと思います。ガジェットシングルトンに行きましょう!
public class Logger {
private static Logger _instance;
public static Logger Instance
{
get
{
if (_instance == null)
_instance = new Logger();
return _instance;
}
set { _instance = value; }
}
protected Logger() { }
public virtual void Log(string s) { ... }
}
public class Client {
public void DoSomething() {
Logger.Instance.Log("DoSomething called");
}
}
したがって、TestLogger : Logger
空のLog
メソッドを使用して、テストロガーのインスタンスをテスト用のシングルトンインスタンスに設定します。プレスト!クライアントコードに影響を与えずに、ロガーの実装をテストまたは実稼働用にホットスワップできます。
以下の理由により、シングルトンはグローバル変数よりも好まれます。
編集:
シングルトンのクールな使用法の1つは、ファクトリメソッドと組み合わせると、 フライウェイトパターン を作成するために使用できることです。これは、新しいオブジェクトを作成するときに、ファクトリが(新しいオブジェクトを作成する代わりに)最初にそのオブジェクトのシングルトンがすでに作成されていることを確認します。作成されている場合は、そのオブジェクトを返すだけです。そうでない場合は、新しいシングルトンを作成します。作成したシングルトンを追跡しながら、それを返します。フライウェイトは、シングルトンの不変性のために機能します。
シングルトンはいつも私には少し冗長に見えました。私は静的クラスを好み、異なる動作が必要な場合は、依存関係の注入とプロバイダーと組み合わせます。これがどのようなパターンであるか、または名前があるかどうかはわかりませんが、通常は次のようになります。
public interface IFooProvider {
Bar FooBar();
}
public static class Foo {
public static readonly IFooProvider FooProvider { get; set; }
public Bar FooBar() { return FooProvider.FooBar(); }
}
次に、プロバイダーをinitメソッドのどこかに設定するようにします。クラスの初期化時にデフォルトのプロバイダーを設定する場合は、遅延初期化を追加するのは簡単です。何よりも、静的クラスを使用する美学を維持しながら、動作を変更することができます。
IMHOのシングルトンパターンはかなり使い古されたパターンですが、次のような利点がある場合があります。
多くの言語では、静的クラスには、継承(およびより一般的にはポリモーフィズム)などの便利な機能がありません。
( 私はそうではありませんシングルトンを提唱 。)
シングルトンは従来のクラスアプローチを維持し、どこでもstaticキーワードを使用する必要はありません。最初は実装がより難しいかもしれませんが、プログラムのアーキテクチャを大幅に簡素化します。静的クラスとは異なり、パラメータまたはオブジェクトとしてシングルトンを使用できます。
また、他のクラスと同じように、インターフェイスでシングルトンを使用できます。