<aside> đ đ Category: Creational Pattern
</aside>
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>
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.
All implementations of the Singleton pattern have these two steps in common:
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;
}
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
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);