Singleton Design Pattern in Software Development

Siddharth Phatarphod
5 min readMar 30, 2021

--

Singleton Design Pattern

It has been quite sometime since I wanted to visit this topic of the Singleton Design Pattern in Software Development.

If you have ever given a technical interview and have been asked about any design patterns that you have worked on, this is the famous design pattern that most of you would have mentioned.

On the surface it seems to be the simplest of the design patterns, but it has certain depth in understanding that needs to be fathomed before you can implement it correctly.

I am assuming that you have some familiarity with what software design patterns are.

They are certain tried and tested ways of writing a software program such that they solve the common programming problems.
They act as guideline templates and their implementations differ depending on the programming language you choose for your solution.

So, for a novice what does he need to know before he can delve into these design patterns?

Look for these terms — Object Oriented Programming(OOP), SOLID Principles and get a grasp at the basic level.

At a high level the software design patterns are categorized into three basic types
1. Creational
2. Structural
3. Behavioral

Now, to jump to our topic of interest — the Singleton design pattern falls in the Creational category.

The name Singleton itself suggests that the design pattern is referring to only one or single and thats right — this design pattern when implemented properly would ensure that only a single instance of the class exists that can be accessed globally throughout the program — this class in the design patterns terminology is called as the singleton class.

The goal of the Singleton Design pattern is to provide global access to a singleton class that is restricted to one instance.

Some of the real world use cases of the Singleton Design pattern are as below:
· Access to file system
· Access to shared network resource
· One time configuration settings
· Logging
· Caching
· Thread pools
· Driver objects

Singleton Explained:

  1. Singleton Design Pattern creates only one instance of a singleton class that is globally accessible
  2. A Singleton class
    • Has a single, private, parameter less constructor
    • This prevents sub classing
    • Is marked as sealed to help optimize the JIT compiler (assuming .NET C# implementation)
    • Has a private variable (static field) that creates one unique instance (assuming .NET C# implementation)
    • Has a public static method to return or to create and return the singleton class instance (assuming .NET C# implementation)
  3. Singleton classes are created without parameters
  4. It has lazy instantiation by default — created only when needed
  5. Default implementation has issues when multiple threads try to access the shared single object

Referring to C# in .NET, you can implement the Singleton Design Pattern in one of the below ways:

1. Default implementation — this is not thread safe
2. Lock Object implementation — this is thread safe but has performance overhead
3. Double Check locking — this is thread safe and has performance improvement
4. Thread safe without locks
5. Full lazy instantiation
6. Using .NET 4 Lazy<T> type

Singleton Implementations in .NET C#

1. Singleton Implementation default that is not thread-safe

public sealed class Singleton
{
private static Singleton _instance=null;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (_instance==null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
The above implementation will create multiple instances if called by multiple threads in parallel.

2. Singleton Implementation thread-safe using lock

public sealed class Singleton
{
private static Singleton _instance = null;
private static readonly object padlock = new object();
Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
}
The above thread-safe implementation has a performance overhead as with every use of the Instance property will incur overhead of the lock.
The lock must be a dedicated private instance variable and not a shared, public or static value that can be used by another lock elsewhere in the application.

3. Singleton Implementation using double-checked locking

public sealed class Singleton
{
private static Singleton _instance = null;
private static readonly object padlock = new object();
Singleton()
{
}
public static Singleton _instance
{
get
{
if (_instance == null)
{
lock (padlock)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
The above implementation has null check twice and lock is implemented in between those two checks. We only fetch the lock when the instance is null. when the application starts up or the first request is made to this instance. Performance is improved as the lock is not checked as often.
This implementation does not conform to the ECMA CLI specification.

4. Singleton Implementation thread safe static instance without using locks

public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}

The use of Static in above implementation, creates the instance on the first member reference and is hence not a lazy implementation.
Complications arise if there is a cyclic reference of the static constructors.
Performance is affected due to the non-laziness of this implementation.

5. Singleton Implementation using fully lazy Instantiation

public sealed class Singleton
{
private Singleton()
{
}
public static Singleton Instance { get { return Nested.instance; } }
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
The above implementation with a nested class supports full lazy implementation without any performance overheads.

6. Singleton Implementation using .NET 4’s Lazy<T> type

public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
In the above implementation, you pass a delegate to the constructor which calls the Singleton constructor — which is done most easily with a lambda expression.
It also allows you to check whether or not the instance has been created yet with the IsValueCreated property.
The code above implicitly uses LazyThreadSafetyMode.ExecutionAndPublication as the thread safety mode for the Lazy<Singleton>.

Coming soon : Some FAQ’s and interview questions on the Singleton Design Pattern

References:
1. https://csharpindepth.com/articles/singleton
2. https://refactoring.guru/design-patterns/singleton

--

--

Siddharth Phatarphod
Siddharth Phatarphod

Written by Siddharth Phatarphod

Full Stack | Angular| .Net| .Net Core| SQL | Azure PaaS | Azure DevOps | Git | Scrum

No responses yet