用decorator实现python单例模式

在 python 里实现单例模式有许多方法,个人觉得还是基于 decorator 的方法最优雅。

从 stackoverflow 上找到一个实现,我将它改成了线程安全的,记录如下:

import threading

class 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 就可以了,如下:

@Singleton
class MySingletonClass: pass

s1 = MySingletonClass.Instance()
s2 = MySingletonClass.Instance()

s1 和 s2 就是相同的实例。

附上一个简单的 testcase:


import unittest
from singleton import Singleton

@Singleton
class A: pass

class 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()



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值