Ответ
Singleton (Одиночка) — это порождающий паттерн проектирования, который гарантирует наличие только одного экземпляра класса и предоставляет глобальную точку доступа к нему.
Основные цели паттерна:
- Единственный экземпляр: В системе не может быть создано более одного объекта этого класса.
- Глобальный доступ: Предоставляет единую точку для доступа к этому экземпляру из любой части программы.
Классическая реализация в Python
Один из способов реализации — переопределение метода __new__:
import threading
class Singleton:
_instance = None
_lock = threading.Lock() # Для потокобезопасности
def __new__(cls, *args, **kwargs):
# Проверяем, был ли уже создан экземпляр
if not cls._instance:
# Блокируем доступ для других потоков
with cls._lock:
# Повторная проверка внутри блока на случай, если другой поток создал экземпляр
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
# Проверка
s1 = Singleton()
s2 = Singleton()
print(f"s1 is s2: {s1 is s2}") # Вывод: s1 is s2: True
Когда это полезно?
- Управление общими ресурсами: Подключение к базе данных, управление пулом потоков.
- Глобальная конфигурация: Хранение настроек приложения, доступных из любой точки.
- Логгирование: Единый объект логгера для всей системы.
Риски и критика
Singleton часто считают анти-паттерном, так как он:
- Создает глобальное состояние, что усложняет тестирование и отладку.
- Нарушает принцип единственной ответственности (SRP): класс отвечает и за свою бизнес-логику, и за контроль количества экземпляров.
Альтернатива в Python
В Python модули по своей природе являются синглтонами. При первом импорте модуль выполняется и кэшируется. Все последующие импорты возвращают ссылку на уже существующий объект модуля. Часто для хранения глобального состояния или конфигурации достаточно создать обычный Python-файл (config.py) и импортировать его.