Advertisement
viking_unet

Singleton right pattern case with true behavior

Apr 18th, 2020
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.96 KB | None | 0 0
  1. import weakref
  2.  
  3. class UserException(Exception): pass
  4.  
  5. class MetaSingleton(type):
  6.    
  7.     _instance = []
  8.    
  9.     def __call__(cls, *args, **kwargs):
  10.        
  11.         if not cls._instance:
  12.             cls._instance.append(type.__call__(cls, *args, **kwargs))
  13.         else:
  14.             if args or kwargs: raise UserException("can't recreate singleton with new args until old will be cleared")
  15.         return weakref.proxy(cls._instance[0])
  16.  
  17. class Singleton(metaclass = MetaSingleton):
  18.    
  19.     def __init__(self, *args, **kwargs):
  20.         # полное игнорирование новых аргументов конструктора
  21.         # т.к. сюда даже не попадаем при повторном создании экземпляра одиночки
  22.        
  23.         print('singleton.__init__')
  24.         self.x = args[0]
  25.         self.y = kwargs['y']
  26.        
  27.     def clear(self):
  28.         # здесь должны быть все действия по корректному разрешению
  29.         # всех коллизий с уже созданными внутри объектами от прошлого одиночки
  30.        
  31.         print('singleton cleared')
  32.         MetaSingleton._instance.pop()
  33.  
  34.     def __del__(self):
  35.         # метод удаления вызывается сборщиком мусора только когда все ссылки на экземпляр теряются
  36.        
  37.         print('__del__')
  38.    
  39.     def test(self, x = None):
  40.         # тестовый метод класса одичноки - любая бизнес-логика в качестве методов
  41.        
  42.         self._x = x
  43.         return self._x
  44.  
  45. # создали три экземпляра одиночки:
  46. # - первый с аргументами (создание и настройка единственного экземпляра)
  47. # - второй без аргументов (чисто копия ссылки на экземпляр)
  48. # - третий с новыми аргументами (возбуждаем исключение, т к одиночку нужно пердварительно очистить !)      
  49. s = Singleton(1, y = 2)
  50. print("Object created (fist time)", s, s.__dict__)
  51. ss = Singleton()
  52. print("Object created (copy without args)", ss, ss.__dict__)
  53. try:
  54.     sss = Singleton(10, y = 20)
  55. except Exception as err:
  56.     print("Object not created (exception - try to call with args after fist time and without clear):", err)
  57. """
  58. >> singleton.__init__
  59. >> Object created (fist time) <__main__.Singleton object at 0x00323D90> {'x': 1, 'y': 2}
  60. >> Object created (copy without args) <__main__.Singleton object at 0x00323D90> {'x': 1, 'y': 2}
  61. >> Object not created (exception - try to call with args after fist time and without clear):
  62. >> can't recreate singleton with new args until old will be cleared
  63. """
  64.  
  65. # очищаем любой из созданных копий одиночки
  66. s.clear()
  67. """
  68. >> singleton cleared
  69. >> __del__
  70. """
  71.  
  72. # пробуем вывести данные по каждой копии одиночки после очистки,
  73. # должно быть исключение - ссылки на оригинальный экземпляр больше нет
  74. try: print(s)
  75. except Exception as err:
  76.     print('try ro print first singleton copy variable:', err)
  77. try: print(ss)
  78. except Exception as err:
  79.     print('try ro print second singleton copy variable:', err)
  80. """
  81. >> try ro print first singleton copy variable: weakly-referenced object no longer exists
  82. >> try ro print second singleton copy variable: weakly-referenced object no longer exists
  83. """
  84.  
  85. # заново создаём новый
  86. s = Singleton(10, y = 20)
  87. print("Object recreated", s, s.__dict__)
  88. res = s.test(123)
  89. print('test = %s' % res)
  90. """
  91. >> singleton.__init__
  92. >> Object recreated <__main__.Singleton object at 0x00323D90> {'x': 10, 'y': 20}
  93. >> test = 123
  94. """
  95.  
  96. print('done')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement