I have been in software industry for now more than 20+ years. During this 20+ years I have taken countless interviews and seen that candidate after candidate coming with such limited knowledge of design patterns. The moment you ask them about any design pattern they have used and can explain, they will immediately say Singleton pattern. Now most of these software developers (using it in generic terms to include SSE, TL, STL, Architect and Sr. Architects) do not know how to code a simple Singleton implementation. This is across the tech stack - Java, and C# both. You realise almost immediately that they have never thought about their implementations seriously, nor have they done any good reading and worst this just shows their immaturity at software development.
For those who do not know what Singleton is, a quick refresher.
A Singleton class is a class that can have only one instance (or new'ed object) at a time. If we try to get instances of this class it will always return the same instance.
Lets look at some typical code that you get to see for Singleton pattern.
Incorrect version 1 (C#)
public class Singleton {
private Singleton singleton = new Singleton();
public Singleton getInstance() {
return singleton;
}
}
Providing getInstance and making the instance variable private does not make it Singleton.
Incorrect version 2 (C#)
public class Singleton {
private Singleton singleton = null;
public Singleton getInstance() {
singleton = new Singleton();
return singleton;
}
}
Moving initialization to getInstance method does not make it Singleton. Anyone can do a new instantiation of this Singleton class.
Incorrect version 3 (C#)
public class Singleton {
public Singleton singleton = new Singleton();
private Singleton() {}
}
Making the constructor private does not make this implementation Singleton. In-fact, now there is no way to initialize this class.
Incorrect version 4 (C#)
public class Singleton {
private Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
singleton = new Singleton();
return singleton;
}
}
This is incorrect because you cannot work with instance variables from static method.
Incorrect version 5 (C#)
public class Singleton {
private Singleton singleton = null;
private Singleton() {}
public Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
This implementation will never work since constructor is private so you cannot even get to getInstance.
Incorrect version 6 (C#)
public class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
This implementation is almost there but not enough, because this is not thread safe.
When implementing Singleton you should consider
- Making the class non-inheritable
- Making the instance variable static
- Making the constructor private
- Providing for static getInstance
- Making it thread safe
So lets take a look at a better version of Singleton implementation that is not thread safe.
Better version (C#)
public sealed class Singleton {
private static Singleton singleton = null;
private Singleton() {}
static Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
Now, lets see how to make it thread safe. People who get this far will be able to write thread safe code as follows:
Incomplete thread safe version (C#)
public sealed class Singleton {
private static Singleton singleton = null;
private static readonly object syncObject = new object();
private Singleton() {}
static Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
lock(syncObject) {
singleton = new Singleton();
}
}
return singleton;
}
}
Above version is almost there, what it lacks is double check lock to ensure that it executes smoothly in multithreading scenarios.
Final version that addresses all concerns of Singleton and is thread safe looks as below.
Correct version (C#)
public sealed class Singleton {
private static Singleton singleton = null;
private static readonly object syncObject = new object();
private Singleton() {}
static Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
lock(syncObject) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
This is the code that I am looking for when an interview candidate says he knows or has used Singleton Design Pattern.
There is a possibility of making use of readonly along with static to get synchronized behaviour in .Net, this is because CLR makes sure that the static constructor is called only once in synchronized manner.
Simplified alternate version (C#)
public sealed class Singleton {
private readonly static Singleton singleton = new Singleton();
private Singleton() {}
static Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
In Java world you can make use of synchronized modifier for getInstance method instead of making use of lock.
Correct version (Java)
final class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}