<aside> 📚 📁 Category: Creational Pattern

</aside>

Overview

Singleton is a creational design pattern that ensures a class has only one instance and provides a global point of access to that instance. This pattern is useful when exactly one object is needed to coordinate actions across the system.

<aside> â„šī¸ When to use: When you need to ensure that only one instance of a class exists and you need a global access point to that instance. Common uses include logging, database connections, configuration managers.

</aside>

Problem

Sometimes you need to ensure that a class has just a single instance. For example, you want to have a single database connection shared by all objects, or a single configuration object for the entire application.

A regular constructor can't enforce this because a constructor call must always return a new object by design.

Solution

All implementations of the Singleton pattern have these two steps in common:

Implementation in C#

public sealed class Singleton
{
    private static readonly Lazy<Singleton> _instance = 
        new Lazy<Singleton>(() => new Singleton());

    private Singleton()
    {
        // Private constructor prevents instantiation
        Console.WriteLine("Singleton instance created");
    }

    public static Singleton Instance => _instance.Value;

    public void DoSomething()
    {
        Console.WriteLine("Singleton method called");
    }
}

// Usage
var instance1 = Singleton.Instance;
var instance2 = Singleton.Instance;

Console.WriteLine(ReferenceEquals(instance1, instance2)); // True
public sealed class Singleton
{
    private static Singleton _instance;
    private static readonly object _lock = new object();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }
}
public sealed class Singleton
{
    private static readonly Singleton _instance = new Singleton();
    
    // Static constructor ensures thread safety
    static Singleton() { }
    
    private Singleton() { }
    
    public static Singleton Instance => _instance;
}

Implementation in Python

class SingletonMeta(type):
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]

class Singleton(metaclass=SingletonMeta):
    def __init__(self):
        print("Singleton instance created")
    
    def do_something(self):
        print("Singleton method called")

# Usage
instance1 = Singleton()
instance2 = Singleton()

print(instance1 is instance2)  # True
def singleton(cls):
    instances = {}
    
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    
    return get_instance

@singleton
class DatabaseConnection:
    def __init__(self):
        self.connection = "Connected to database"
    
    def query(self, sql):
        return f"Executing: {sql}"

# Usage
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True

Real-World Example: Configuration Manager

public sealed class ConfigurationManager
{
    private static readonly Lazy<ConfigurationManager> _instance = 
        new Lazy<ConfigurationManager>(() => new ConfigurationManager());

    private readonly Dictionary<string, string> _settings;

    private ConfigurationManager()
    {
        // Load configuration from file
        _settings = new Dictionary<string, string>
        {
            { "DatabaseConnection", "Server=localhost;Database=mydb" },
            { "ApiKey", "your-api-key" },
            { "MaxRetries", "3" }
        };
    }

    public static ConfigurationManager Instance => _instance.Value;

    public string GetSetting(string key)
    {
        return _settings.TryGetValue(key, out var value) ? value : null;
    }

    public void SetSetting(string key, string value)
    {
        _settings[key] = value;
    }
}

// Usage
var config = ConfigurationManager.Instance;
string dbConnection = config.GetSetting("DatabaseConnection");
Console.WriteLine(dbConnection);