Добавить в корзинуПозвонить
Найти в Дзене
Python Django

Singleton (Одиночка) — порождающий шаблон проектирования, гарантирующий, что в однопроцессном приложении будет единственный экземпляр

Singleton (Одиночка) — порождающий шаблон проектирования, гарантирующий, что в однопроцессном приложении будет единственный экземпляр некоторого класса, и предоставляющий глобальную точку доступа к этому экземпляру. 📎 Реализация синглтона через декоратор класса: def singleton(cls): # храним все разные синглтоны с одном словаре (класс -> экземпляр) instances = {} def getinstance(): # если класса нет среди ключей нашего словаря - создадим экземпляр if cls not in instances: instances[cls] = cls() # вернем ссылку на него return instances[cls] return getinstance Вот так мы помечаем, что класс MySingleton – синглтон: @singleton class MySingleton: def __init__(self): self.x = 10 print("__init__") 📎 Пример (проверяем единственность экземляра): >>> x1 = MySingleton() init >>> x2 = MySingleton() >>> x1 is x2 True >>> x1.x = 100 >>> x2.x 100 • init было вызвано единажды • Обе переменные указывают на один экземпляр • При изменении полей в одном экземпляре, они меняются и во втором. Плохо то, что

Singleton (Одиночка) — порождающий шаблон проектирования, гарантирующий, что в однопроцессном приложении будет единственный экземпляр некоторого класса, и предоставляющий глобальную точку доступа к этому экземпляру.

📎 Реализация синглтона через декоратор класса:

def singleton(cls):

# храним все разные синглтоны с одном словаре (класс -> экземпляр)

instances = {}

def getinstance():

# если класса нет среди ключей нашего словаря - создадим экземпляр

if cls not in instances:

instances[cls] = cls()

# вернем ссылку на него

return instances[cls]

return getinstance

Вот так мы помечаем, что класс MySingleton – синглтон:

@singleton

class MySingleton:

def __init__(self):

self.x = 10

print("__init__")

📎 Пример (проверяем единственность экземляра):

>>> x1 = MySingleton()

init

>>> x2 = MySingleton()

>>> x1 is x2

True

>>> x1.x = 100

>>> x2.x

100

• init было вызвано единажды

• Обе переменные указывают на один экземпляр

• При изменении полей в одном экземпляре, они меняются и во втором.

Плохо то, что MySingleton здесь – это функция (результат работы декоратора), а не класс: вы не можете вызывать класс-методы у нее. Эта проблема решается использованием метаклассов.

# обратите внимание, метакласс наследован от type

class Singleton(type):

_instances = {}

def __call__(cls, *args, **kwargs):

if cls not in cls._instances:

cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)

return cls._instances[cls]

Применение (Python 3):

class MySingleton(metaclass=Singleton):

def __init__(self):

self.x = 10

print("__init__")

⚠️ Не злоупотребляйте синглтонами, они осложняют тестирование кода.