What is the Singleton Pattern?
The Singleton Design Pattern is a creational pattern that ensures only one instance of a class is created and provides a global access point to that instance.
In simple terms, imagine you have a class that should only ever have one object (like a single log manager, configuration handler, or shared resource). The Singleton pattern helps you do exactly that.
When to Use Singleton Pattern?
Use Singleton when,
- You need to limit a class to a single instance.
- You want to control access to shared resources like file handlers, database connections, logging services, etc.
- You want a centralized object that's reused throughout the application.
Basic Structure of Singleton Pattern
Key Points
- Private constructor to prevent external instantiation.
- Static variable to hold the single instance.
- Public static method or property to provide access.
Basic Example
public sealed class Singleton
{
private static Singleton instance = null;
// Private constructor to prevent object creation
private Singleton()
{
Console.WriteLine("Singleton instance created");
}
// Public method to get the instance
public static Singleton GetInstance()
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
Thread-Safe Singleton
In multi-threaded applications, the basic version might create multiple instances. So we make it thread-safe:
Using Lock
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object lockObj = new object();
private Singleton() { }
public static Singleton GetInstance()
{
lock (lockObj)
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
}
}
Best Practice: Lazy Initialization
C# also provides an easy way using Lazy<T>.
public sealed class Singleton
{
private static readonly Lazy<Singleton> instance =
new Lazy<Singleton>(() => new Singleton());
private Singleton() { }
public static Singleton Instance => instance.Value;
}
Eager vs Lazy Loading
Approach |
Description |
Eager |
The instance is created at application start. Good for performance-critical cases. |
Lazy |
The instance is created when it's needed. Saves memory and start-up time. |
Drawbacks of Singleton
- Can make unit testing difficult (tight coupling).
- It might be overused when a simple static class would do.
- Risk of hidden dependencies across the app.
Real-Time Use Cases
- Logger
- Configuration settings
- Database connection manager
- Caching mechanism
Summary
- Singleton ensures one instance only.
- It’s helpful for managing shared resources.
- Make it thread-safe for multi-threaded apps.
- Use lazy loading for better performance when n