Singleton is a creational design pattern. I think even a junior developer should know at least this design pattern. It’s the most used design pattern and is simple.
This pattern solves the problem when you want to have only one instance. For example, let’s think about a connection to a server. You don’t want to open multiple connections from the same application, but you instantiate the object from many other classes. Practically, you provide a global point of access to that instance.
The intent is to have only one instance of the class in the system, which makes it possible for other objects to access it.
Probably, you wonder why don’t you use a static class for this scenario:
- The advantage of the Singleton pattern is that you can use the object to pass to other methods.
- You can use the OOP principles in Singleton classes.
- A static class cannot be inherited.
- You can dispose a singleton object. A static class cannot be disposed.
- A singleton object is stored on the heap instead of the stack. A static class is held on the stack.
Some real scenarios when you need Singleton Pattern
- When you want a single connection to the database/server
- To keep a single access point to the configuration. For example, the SharedPreferences class in Android.
- Single management of costly resources
- For network connections
How to implement the Singleton Pattern in C#?
There are multiple ways to implement this pattern, but some of them have some disadvantages. The final form from this article is the best and is safe to use.
For each implementation, you will need to make the constructor private. You want to forbid the initialization of an object by using the constructor. We want to hide the initialization of the object. Practically, we want that the initialization to be internal. We achieve this step by making the constructor private. We will have a static method that returns the instance of the object. Also, we need a private static instance of that object inside of that class.
internal class ServerConnection { private static ServerConnection _connection; private ServerConnection() { } public static ServerConnection GetServerConnection() { if (_connection==null) { _connection = new ServerConnection(); } return _connection; } }
In the above code, you can see that inside the static method, we check to see if there is already or not an instance of that class. If there is already an instance, then it returns it. Otherwise, it creates a new one.
A tremendous advantage of the Singleton pattern is lazy instantiation. Your instance will be first instantiated only when you first call it.
Simple Singleton
This is the first variant that you learn.
The above code shows you a simple Singleton pattern. Please don’t use it! It is only for learning purposes!
public static ServerConnection GetServerConnection() { if (_connection==null) // thread 1 enters first and the condition is true. The thread doesn't yet execute the below code that initialize the thread. The condition it will be still true for the second thread. { _connection = new ServerConnection(); // } return _connection; }
Simple doesn’t mean that this is the desired solution. This method is problematic if you call the GetInstance method from a multi-thread application. There is a big possibility that two threads will enter into the static method that returns an instance. Both will execute the if statement, and because the model is not initialized, each will create a new one.
Thread Safe Singleton
A thread-safe Singleton is necessary. Forget simple singleton!
In this case, I will use the lock statement to ensure that only one thread checks the condition and initializes the object.
internal sealed class ServerSafeSingleton { private static ServerSafeSingleton _serverInstace; private static object padLock = new object(); private ServerSafeSingleton() { } public static ServerSafeSingleton GetServerConnection() { lock (padLock) { if (_serverInstace == null) // only one thread at a time can execute this line { _serverInstace = new ServerSafeSingleton(); } return _serverInstace; } } }
Thread Safe Singleton without lock statement
Here is a simple solution:
internal sealed class ServerSafeSingleton { private static readonly ServerSafeSingleton _serverConnection= new ServerSafeSingleton(); static ServerSafeSingleton() { } private ServerSafeSingleton() { } public static ServerSafeSingleton Instance { get { return _serverConnection; } } }
Singleton Pattern Using Lazy class
Lazy class to create objects using lazy instantiation. So until the first thread needs it, the object is not created. After the first thread executes, the following threads will already have an instance.
internal sealed class ServerLazySingleton { private static readonly Lazy<ServerLazySingleton> lazy = new Lazy<ServerLazySingleton>(() => new ServerLazySingleton()); public static ServerLazySingleton Instance { get { return lazy.Value; } } private ServerLazySingleton() { } }
Conclusions about Singleton Pattern
I advise you always to use the Singleton Pattern, which is multi-thread safe. I usually like to implement the Singleton pattern using lock statements.
Don’t forget that the Singleton pattern is used in many projects, so pay attention and learn how to use it. Probably, you will also receive interview questions about it. Here are the main things to remember:
- Private constructor
- A private static member of that class
- A static method or property that returns the instance