Я подброшу на ринг. Это простой декоратор.
from abc import ABC
def singleton(real_cls):
class SingletonFactory(ABC):
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = real_cls(*args, **kwargs)
return cls.instance
SingletonFactory.register(real_cls)
return SingletonFactory
# Usage
@singleton
class YourClass:
... # Your normal implementation, no special requirements.
Преимущества Я думаю, что он имеет некоторые из других решений:
YourClass
. Это означает, что вам не нужно использовать метакласс для вашего класса (обратите внимание, что метаклас выше находится на фабрике, а не «реальный» класс). YourClass
, он выглядит как класс (потому что это так), и они обычно используют его. Нет необходимости адаптировать вызывающих абонентов к заводской функции. То, что YourClass()
создает экземпляр, по-прежнему является истинным экземпляром YourClass
, который вы внедрили, а не прокси-сервером любого типа, поэтому никаких шансов на побочные эффекты в результате этого. isinstance(instance, YourClass)
и подобные операции все еще работают как ожидалось (хотя этот бит требует abc, поэтому исключает Python & lt; 2.6). Для меня имеет место один недостаток: classmethods и staticmethods реального класса не могут быть прозрачно вызваны с помощью класса фабрики, скрывающего его. Я использовал это достаточно редко, что мне никогда не приходилось сталкиваться с этой необходимостью, но его можно было бы легко исправить, используя специальный метакласс на заводе, который реализует __getattr__()
, чтобы делегировать доступ к атрибуту all-ish для реального класса.
Связанный шаблон, который я действительно нашел более полезным (не то, что я говорю, что такие вещи требуются очень часто вообще) является «уникальным» шаблоном, где экземпляр класса с помощью те же аргументы приводят к возврату одного и того же экземпляра. То есть «одиночный аргумент». Вышеприведенное адаптируется к этой скважине и становится еще более кратким:
def unique(real_cls):
class UniqueFactory(ABC):
@functools.lru_cache(None) # Handy for 3.2+, but use any memoization decorator you like
def __new__(cls, *args, **kwargs):
return real_cls(*args, **kwargs)
UniqueFactory.register(real_cls)
return UniqueFactory
Все, что сказал, я согласен с общим советом, что, если вы считаете, что вам нужна одна из этих вещей, вам действительно стоит остановиться на и спросите себя, действительно ли вы это делаете. 99% времени, YAGNI.
Звучит скорее как проблема в том, что когда данные кэшируются, событие загрузки срабатывает, прежде чем прикрепить обработчик.
Что вы можете попробовать, это сбросить атрибут данных после присоединения события :
object.addEventListener('load', onload_handler);
// reset the data attribte so the load event fires again if it was cached
object.data = object.data;