Singleton (Одиночка) — это порождающий паттерн проектирования, который гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру.
public sealed class Singleton
{
private static Singleton _instance;
private static readonly object _lock = new object();
// Закрытый конструктор
private Singleton()
{
// Инициализация
}
public static Singleton Instance
{
get
{
lock (_lock) // Потокобезопасность
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
public void SomeBusinessLogic()
{
// ...
}
}
Управление общими ресурсами:
Контроль доступа:
Координация действий:
Singleton.Instance
[Test]
public void TestService()
{
var mock = new Mock<IDatabase>();
// Невозможно подменить реальный Singleton тестовой заглушкой
var service = new SomeService(Singleton.Instance); // Проблема!
}
public interface IMyService {}
public class MyService : IMyService {}
// Регистрация как Singleton в DI-контейнере
services.AddSingleton<IMyService, MyService>();
Преимущества:
Lazy initialization:
public sealed class ImprovedSingleton
{
private ImprovedSingleton() { }
public static ImprovedSingleton Instance =>
LazyInitializer.EnsureInitialized(ref _instance);
private static ImprovedSingleton _instance;
}
Использование Lazy
public sealed class ThreadSafeSingleton
{
private static readonly Lazy<ThreadSafeSingleton> _instance =
new Lazy<ThreadSafeSingleton>(() => new ThreadSafeSingleton());
public static ThreadSafeSingleton Instance => _instance.Value;
private ThreadSafeSingleton() { }
}
Singleton — это обоюдоострый меч. Хотя он решает конкретные проблемы глобального доступа, его частое использование ведет к жестко связанному коду, который трудно тестировать и поддерживать. В современных приложениях предпочтительнее использовать Dependency Injection для управления жизненным циклом объектов, сохраняя преимущества Singleton без его недостатков.