美文网首页
设计模式-单例-Python实现

设计模式-单例-Python实现

作者: 小温侯 | 来源:发表于2018-07-20 23:24 被阅读37次

    单例是什么?

    单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。

    维基百科-单例模式

    简单来说,就是某种类,它有且就有一个实例。

    在Python中怎么实现

    重写__new__方法

    __new__是类在创建时(不是实例化)时会调用的成员方法,其参数是这个类本身,即cls。这里我们使用hasattr方法来判断一个类有没有实例。如果没有就新建一个,有的话就返回当前的那个。这样就保证了这个类永远只会有一个实例。

    # singleton
    class Singleton(object):
        def __new__(cls):
            if not hasattr(cls, '_instance'):
                cls._instance = super(Singleton, cls).__new__(cls)
            return cls._instance
    
    class MyClass(Singleton):
        a = 1
    
    
    A = MyClass()
    B = MyClass()
    
    print (A is B)
    

    装饰器实现

    这个方法的核心思想就是将对象的实例用其他的容器保存下来,每次实例类的时候,装饰器会判断这个类是不是已经在容器中了。如果是,则直接返回容器中的实例,否则则新建一个实例返回并放入容器中。容器中最多只会有一个值。

    # singleton
    def singleton(cls):
        instances = {}
        def getinstance(*args, **kwargs):
            if cls not in instances:
                instances[cls] = cls(*args, **kwargs)
            return instances[cls]
        return getinstance
    
    @singleton
    class MyClass():
        a = 1
    
    A = MyClass()
    B = MyClass()
    
    print (A is B)
    

    用list 也可以

    # singleton
    def singleton(cls):
        instances = []
        def getinstance(*args, **kwargs):
            if not instances:
               instances.append(cls(*args, **kwargs))
            return instances[0]
        return getinstance
    
    @singleton
    class MyClass():
        a = 1
    
    A = MyClass()
    B = MyClass()
    
    #print (len(A))
    print (A is B)
    

    这样也可以

    # singleton
    instances = None
    def singleton(cls):
        def getinstance(*args, **kwargs):
            global instances
            if not instances:
               instances = cls(*args, **kwargs)
            return instances
        return getinstance
    
    @singleton
    class MyClass():
        a = 1
    
    A = MyClass()
    B = MyClass()
    
    #print (len(A))
    print (A is B)
    

    但是这样不行

    # singleton
    def singleton(cls):
        instance = None
        def getinstance(*args, **kwargs):
            if not instance:
               instance = cls(*args, **kwargs)
            return instance
        return getinstance
    
    @singleton
    class MyClass():
        a = 1
    
    A = MyClass()
    B = MyClass()
    
    #print (len(A))
    print (A is B)
    

    为什么?因为这里构成了闭包,Python只会会把闭包中用到的值保存下来,但是你不能在闭包中对其进行修改。也就是说在这个例子里,你只能访问instance,但是不能对其赋值,否则会报错UnboundLocalError。我会在另外一篇关于作用域和闭包的文章中仔细讲一讲。

    怎么改呢?一种就是用上面的两种方法,将它改成一个列表或者字典,我们不能对列表本身做修改,但是可以对列表中包含的对象做修改;另一种方法则是用关键词nonlocal:

    # singleton
    def singleton(cls):
        instance = None
        def getinstance(*args, **kwargs):
            nonlocal instance
            if not instance:
               instance = cls(*args, **kwargs)
            return instance
        return getinstance
    
    @singleton
    class MyClass():
        a = 1
    
    A = MyClass()
    B = MyClass()
    
    #print (len(A))
    print (A is B)
    

    相关文章

      网友评论

          本文标题:设计模式-单例-Python实现

          本文链接:https://www.haomeiwen.com/subject/cjjcmftx.html