Что это такое
Паттерн Одиночка (Singleton) гарантирует, что у класса есть ровно один экземпляр во всей программе, и даёт всем одну и ту же точку доступа к нему. Типичные одиночки: конфигурация, пул соединений, логгер.
В Python здесь есть преимущество: модуль импортируется только один раз, поэтому объект, созданный на уровне модуля, уже является общим единственным экземпляром. Когда создание должно быть ленивым — выполняться при первом использовании, а не при импорте, — его защищает метод класса, например Config.instance(): он создаёт объект при первом вызове и затем всегда возвращает сохранённый экземпляр.
Пример: одна конфигурация для всех
Конфигурация загружается при первом вызове Config.instance() и больше никогда. Каждый вызывающий код получает один и тот же объект.
Однократная загрузка с защищённым методом класса
Строка «загрузка конфигурации» выводится только один раз, хотя Config.instance() вызывается дважды, — а a is b доказывает, что оба вызова получили один и тот же экземпляр.
Вывод: полная программа на Python
class Config:
_instance = None
def __init__(self, app_name: str):
self.app_name = app_name
# Единственный экземпляр создаётся при первом вызове, затем используется повторно.
@classmethod
def instance(cls) -> "Config":
if cls._instance is None:
print("загрузка конфигурации (происходит один раз)")
cls._instance = cls("PromptCookbook")
return cls._instance
a = Config.instance()
b = Config.instance()
print("приложение:", a.app_name)
print("тот же экземпляр:", a is b)
Когда использовать
Используйте его, когда чего-то действительно должно быть ровно одно: одна загруженная конфигурация, один пул соединений, один кеш — и создание обходится дорого, или дубликаты будут конфликтовать.
Обойдитесь без него, когда можно просто создать значение один раз в начале программы и передать его тем, кому оно нужно. Явная передача зависимостей понятнее глобального доступа — одиночка является последним средством, а не первым.
Плюсы и минусы
Плюсы: гарантированно единственный экземпляр; ленивое создание при первом использовании; система модулей даёт простой случай почти бесплатно.
Минусы: это замаскированная глобальная переменная — скрытые зависимости усложняют понимание кода; в тестах его нелегко заменить подделкой; злоупотребление приводит к запутанным программам.