One good reason for preferring a singleton over a static class (assuming you have no better patterns at your disposal ;) ), is swapping out one singleton instance with another.
For example, if I have a logging class like this:
public static class Logger {
public static void Log(string s) { ... }
}
public class Client {
public void DoSomething() {
Logger.Log("DoSomething called");
}
}
It works really well, but what if Logger writes things to a database, or writes output to the console. If you're writing tests, you probably don't want all those side-effects -- but since the log method is static, you can't do anything except.
Ok, so I want to hot-swap my Log method for testing. Go go gadget singleton!
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");
}
}
So you can define a TestLogger : Logger
with an empty Log
method, then set an instance of your test logger to the singleton instance for tests. Presto! You can hotswap your logger implementation for tests or production without affecting client code.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…