Ответ
Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет к нему глобальную точку доступа.
Зачем это нужно? Для управления общим ресурсом, доступ к которому должен быть координирован из одной точки: кэш, конфигурация, логгер, пул соединений с базой данных.
Классическая потокобезопасная реализация на C# (с двойной проверкой):
public sealed class Singleton
{
// Единственный экземпляр. 'volatile' гарантирует корректную работу в многопоточной среде.
private static volatile Singleton _instance;
private static readonly object _lockObject = new object();
// Приватный конструктор блокирует создание экземпляров через 'new'.
private Singleton() { }
// Публичное статическое свойство для доступа.
public static Singleton Instance
{
get
{
// Первая проверка (для быстродействия, если экземпляр уже создан).
if (_instance == null)
{
lock (_lockObject) // Блокировка для одного потока.
{
// Вторая проверка внутри блокировки.
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
}
Использование:
var config = Singleton.Instance;
Современный и предпочтительный способ в .NET — использование Lazy<T>:
public sealed class Singleton
{
// Lazy<T> обеспечивает ленивую инициализацию и потокобезопасность по умолчанию.
private static readonly Lazy<Singleton> _lazyInstance =
new Lazy<Singleton>(() => new Singleton());
private Singleton() { }
public static Singleton Instance => _lazyInstance.Value;
}
Важно: Паттерн может считаться антипаттерном, если приводит к излишнему глобальному состоянию и усложняет тестирование. В таких случаях лучше использовать внедрение зависимостей (DI), где жизненный цикл объекта (например, AddSingleton) управляется контейнером.