Reputation: 1815
I used to use singleton get a single instance, but it was disclaimed by others because of some disadvantage in testing. What's the disadvantage? Is there any alternative good way for getting a global instance?
So is it OK for me to create only one singleton class Global in application as global hub? so that I can put any other class's single instances in Global.Instance.
Upvotes: 2
Views: 650
Reputation: 19070
Ok, why singletons are bad you can read here: What is so bad about singletons?
Specifically for testing: A typical singleton pattern looks like this
class MyClass
{
private static MyClass m_Instance = new MyClass();
public static MyClass Instance
{
get { return m_Instance; }
}
}
Now imagine you have to run a whole bunch of tests all involving the MyClass.Instance
. This class carries around a state and you usually need to have to have a way to reset it between tests so that each test can start with a clean initial state. Now you can add a Reset()
method but that means you add code to your class just for the purpose of being able to test it which is not desirable.
What to use instead: Well, the singleton in itself is not really the bad thing. The problem it leads to is that it makes it easy to write code like this:
class SomeClass
{
public void SomeMethod()
{
...
MyClass.Instance.DoSomething();
}
}
Now you have created an implicit dependency on the singleton instance you cannot easily break. One approach which solves this problem is via dependency injection (which was already mentioned):
class SomeClass
{
public SomeClass(MyClass myClass)
{
m_MyClass = myClass;
}
public void SomeMethod()
{
...
m_MyClass.DoSomething();
}
}
and you can do:
var someClass = new SomeClass(MyClass.Instance);
in your program and
var someClass = new SomeClass(new MyClass());
for testing.
So singletons are not that bad and sometimes the right tool for the right job, however you need to be careful of how you use them.
Upvotes: 4
Reputation: 8885
Consider using the what is called "ambient context" pattern instead. This example is taken from Mark Seeman's excellent Dependency Injection in .NET book. This pattern gives you the ease of use of a singleton, and also testability. The important point here is the existence of what is called a good "default" (i.e. DefaultTimeProvider shown in the example). Another thing to consider is not to abuse this pattern, in most cases you can inject the different dependencies into the constructor of the class. This pattern should only be used for concerns that cross cut throughout the whole application.
public abstract class TimeProvider
{
private static TimeProvider current;
static TimeProvider()
{
TimeProvider.current = new DefaultTimeProvider();
}
public static TimeProvider Current
{
get { return TimeProvider.current; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
TimeProvider.current = value;
}
}
public abstract DateTime UtcNow { get; }
public static void ResetToDefault()
{
TimeProvider.current = new DefaultTimeProvider();
}
}
Upvotes: 0
Reputation: 3948
Testability is the main difficulty as I can see, to address that to some extent, we have unity containers.
Check Unity container http://unity.codeplex.com/
Upvotes: 1
Reputation: 2646
i dont see any issues with testability and singletons. also i dont see how DI can replace them.
Upvotes: 0