1.定义
一个类只能创建一个对象
为什么使用单例模式:
对于系统中的某些类来说,只有一个实例重要,比如:Windows中只能打开一个任务管理器。如果不使用单例模式,将会弹出多个任务管理器窗口,若显示的内容完全一致,则显示对象重复,浪费内存资源;若显示的内容不一致,则表示在这一瞬间系统有多个状态,与实际不符,也会给用户带来误解。因此确保系统中某个对象的唯一性很重要。
2.实现单例模式的三种方式
(1)装饰器实现单例模式
#装饰器实现单例模式
from functools import wraps
def singleton(cls):
instances={} #key是类名,value是对象名
@wraps(cls)
def wrapper(*args,**kwargs):
name=cls.__name__ #获取类的名字
if instances.get(name):
return instances.get(name) #直接返回缓存中的对象
else:
obj=cls(*args,**kwargs)
instances[name]=obj
return obj
return wrapper
@singleton
class Person(object):
pass
if __name__ == '__main__':
p1=Person()
p2=Person()
print(p1 is p2) #== 判断值是否相等,is判断值和id是否都相等
结果
True
(2)__new__魔术方法实现单例模式
#__new__魔术方法实现单例模式
class Person(object):
def __new__(cls, *args, **kwargs):
print('判断当前类是否拥有instance属性?',hasattr(cls,'instance')) #自省机制hasattr(,,,)判断对象或类是否具有某种属性
if not hasattr(cls,'instance'):
cls.instance=super(Person,cls).__new__(cls)
return cls.instance
def __init__(self,name):
self.name=name
p1=Person('张三')
p2=Person('李四')
print('单例模式是否成功?',p1 is p2)
结果
判断当前类是否拥有instance属性? False
判断当前类是否拥有instance属性? True
单例模式是否成功? True
(3)metaclass自定义元类实现
#metaclass自定义元类实现
class Singleton(type):
cache={}
def __call__(cls):
if cls not in cls.cache:
cls.cache[cls]=super(Singleton,cls).__call__()
return cls.cache[cls]
class Person(object,metaclass=Singleton):
pass
p1=Person()
p2=Person()
print(p1 is p2)
结果
True