单例模式

使用new方法实现单例模式

  每个实例的创建是通过__new__方法,所以如果要实现一个类只能有一个实例就得重写__new__函数。

class A:
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            print("创建了一个实例")
            obj = super().__new__(cls, *args, **kwargs)
            cls._instance = obj
            return obj
        return cls._instance

    def __init__(self):
        print('开始初始化')

执行:

a = A()

输出为:

创建了一个实例
开始初始化

执行:

b = A()

输出为:

开始初始化

执行:

print(id(a), id(b))  # 每个实例的id一样

输出:

140078083206056 140078083206056

 

使用共享属性实现单例模式

  与上一种方法不同的是,此种方法当执行__new__方法后,每次生成一个新的实例。只不过每个实例共享同样的属性,因此实际使用的效果和上面的方法一样。但严格意义上讲,我认为这不算单例。

class A:
    _myDict = {}
    def __new__(cls, *args, **kwargs):
        obj = super().__new__(cls, *args, **kwargs)
        obj.__dict__ = cls._myDict
        print("创建了一个实例")
        return obj
    
    def __init__(self):
        print("开始初始化")

执行:

a = A()

输出为:

创建了一个实例
开始初始化

执行:

b = A()

输出为:

创建了一个实例
开始初始化

执行:

print(id(a), id(b))  # 每个实例的id不一样

输出为:

140078082716952 140078082716504

执行:

a.a = '1'  # 此时对实例a添加一个a属性

pirnt(b.a)  # 通过b得到了与a一模一样的值

 

使用装饰器实现单例模式

  装饰器的特色就是给函数添加额外的功能,同样可以在类上使用装饰器,来限制实例的个数。但此种方法与上两种不同的是,前两种类的__init__方法在生成实例后都被执行了执行了一次,而此种方法只有在第一次生成实例时才调用__init__方法。

def oneObject(cls):
    def wrap(*args, **kwargs):
        if not hasattr(cls, '_instance'):
            obj = cls(*args, **kwargs)
            cls._instance = obj
            return obj
        return cls._instance
    return wrap



@ oneObject
class A:
    def __init__(self):
        print("已经创建了一个实例")

执行:

a = A()

输出为:

已经创建了一个实例

执行:

b = A()  # 注意,没有执行__init__函数

print(id(a), id(b))

输出为:

140357050460928 140357050460928

 

 

posted on 2017-03-12 18:24  科幻vs现实  阅读(256)  评论(0编辑  收藏  举报

导航