- Singleton is single instance provider.
- It ensures a class has only one instance and provides a global point of access to it.
- There are objects that have additional responsibilities and are more global in scope.
- For examples managing limited resources or monitoring the overall state of the system.
- Other reasons quoted for using Singletons are to improve performance.
- A common scenario is when you have a stateless object that is created over and over again.
- Singletons have the unfortunate reputation for being overused by “pattern happy” developers.
public class Singleton
{
private static Singleton _UniqueInstance;
private static readonly object _SyncLock = new Object();
private Singleton() { }
public static Singleton getInstance()
{
lock (_SyncLock)
return _UniqueInstance ?? (_UniqueInstance = new Singleton());
}
}
sealed class EagerSingleton
{
// CLR eagerly initializes static member when class is first used.
// CLR guarantees thread safety for static initialization.
private static readonly EagerSingleton _Instance = new EagerSingleton();
private EagerSingleton() { }
public static EagerSingleton GetInstance() => _Instance;
}
Issues
- Singletons solve one (and only one) problem: Resource Contention.
- They are generally used as a global instance.
- When you think you need a global, you're probably making a terrible design mistake.
- Because you hide the dependencies of your application in your code, instead of exposing them through the interfaces.
- Making something global to avoid passing it around is a code smell.
- They violate the single responsibility principle:
- By controlling their own creation and lifecycle.
- They inherently cause code to be tightly coupled.
- This makes faking them out under test rather difficult in many cases.
- They carry state around for the lifetime of the application.
- Another hit to testing since you can end up with a situation where tests need to be ordered which is a big no no for unit tests.
- Because each unit test should be independent from the other.
Rules of Thumb
- Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
- Facade objects are often Singletons because only one Facade object is required.
- State objects are often Singletons.
- The advantage of Singleton over global variables is that you are absolutely sure of the number of instances when you use Singleton, and, you can change your mind and manage any number of instances.
- Singletons are intended to be used when a class must have exactly one instance, no more, no less.
- Designers frequently use Singletons in a misguided attempt to replace global variables.
- Singleton is unnecessary when it's simpler to pass an object resource as a reference to the objects that need it, rather than letting objects access the resource globally.
- The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object.
- Finding the right balance of exposure and protection for an object is critical for maintaining flexibility.
- The answer to the global data question is not, "Make it a Singleton." The answer is, "Why are you using global data?"
- When Singletons are implementing Serializable interface, they have to consider avoiding multiple objects.