在 python 裡實現單例模式有許多方法,個人覺得還是基於 decorator 的方法最優雅。
從 stackoverflow 上找到一個實現,我將它改成了安全執行緒的,記錄如下:
import threadingclass Singleton: """ A class to ease implementing singletons. This should be used as a decorator -- not a metaclass -- to the class that should be a singleton. The decorated class can define one `__init__` function that takes only the `self` argument. Other than that, there are no restrictions that apply to the decorated class. To get the singleton instance, use the `Instance` method. Trying to use `__call__` will result in a `TypeError` being raised. Limitations: The decorated class cannot be inherited from. """ def __init__(self, decorated): self._decorated = decorated self.lock = threading.Lock() def Instance(self): """ Returns the singleton instance. Upon its first call, it creates a new instance of the decorated class and calls its `__init__` method. On all subsequent calls, the already created instance is returned. """ try: return self._instance except AttributeError: self.lock.acquire() try: return self._instance except AttributeError: self._instance = self._decorated() return self._instance finally: self.lock.release() def __call__(self): raise TypeError('Singletons must be accessed through `Instance()`.') def __instancecheck__(self, inst): return isinstance(inst, self._decorated)
使用時,只要未需要實現 singleton 的類添加一個 decorator 就可以了,如下:
@Singletonclass MySingletonClass: passs1 = MySingletonClass.Instance()s2 = MySingletonClass.Instance()
s1 和 s2 就是相同的執行個體。
附上一個簡單的 testcase:
import unittestfrom singleton import Singleton@Singletonclass A: passclass TestSingleton(unittest.TestCase): def testSingleton(self): a = A.Instance() aa = A.Instance() self.assertTrue(a is aa) def testSingletonCall(self): self.assertRaises(TypeError, A) def testIsinstance(self): a = A.Instance() self.assertTrue(isinstance(a, A)) self.assertFalse(isinstance(a, list))if __name__ == "__main__": unittest.main()