Паттерны проектирования
10. Паттерн «Одиночка» (Singleton). Начало
По определению паттерн «Одиночка» гарантирует, что у некоего класса есть лишь один экземпляр. В некоторых случаях анализ предметной области строго требует, чтобы класс существовал лишь в одном экземпляре. Однако на практике «Синглтон» обычно используется для обеспечения доступа к какому-либо ресурсу, который требуется разным частям приложения.
Назначение: гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему. Другими словами, синглтон эмулирует глобальные переменные в объектно-ориентированных языках программирования.
Причины использования:
Практически в любом приложении возникает необходимость в глобальных переменных или объектах с ограниченным числом экземпляров. И самый простой способ решить эту задачу — создать глобальный объект, который будет доступен из любой точки приложения.
Классическая диаграмма приведена на рисунке ниже.
В оригинальном описании паттерна «Синглтон» «бандой четырех» на его реализацию не накладывались никакие ограничения, однако на практике любая реализация должна отвечать двум требованиям:
- в многопоточной среде должна обеспечиваться возможность доступа к синглтону;
- должна обеспечиваться «ленивость» создания синглтона.
Реализация на основе Lazy<T> (.Net 4.0+):
public sealed class LazySingletonГлавными недостатками синглтонов считаются невозможность юнит-тестирования классов, которые пользуются услугами синглтона, и низкая гибкость. Но при небольшой модификации это можно исправить. Основная суть такой модификации состоит в том, что статическое свойство
{
private static readonly Lazy<LazySingleton>
_instance =
new Lazy<LazySingleton>(
() => new LazySingleton());
LazySingleton() { }
public static LazySingleton Instance {
get { return _instance.Value; }
}
}
Instance вместо возврата конкретного класса возвращает экземпляр абстрактного класса или интерфейса. Также появляется мутатор (set) свойства, который позволяет установить нужный экземпляр синглтона при старте приложения, во время смены контекста или во время инициализации юнит-тестов. В результате решение будет более гибким и тестируемым.Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 8.