单例模式,是一种常用的软件设计模式。在他的核心结构中只包含一个被称为单例的特殊类。通过单例模式,可以保证系统中,应用该模式的类只有一个实例。即一个类只有一个对象实例。
1.控制实例数量(如:要求生产唯一的序列号)
2.节省内存资源,避免频繁创建和销毁
3.保证一个类仅有一个实例,并提供一个访问它的全局访问点。
这里先写两种常用方法
方法一
通过装饰器来设计单例
由于装饰器的外部函数只能执行一次,故我们设置一个flag标记,当对象成功创建后,flag指向创建的对象
#这里我们演示一下外部函数只执行一次的效果
def singe(func):
print("外部")#调用singe装饰器后,这个地方只执行一次
def wrapper(*args,**kwargs):
print("内部函数")
func(*args,**kwargs)
return wrapper
@singe#语法糖,再@的时候就会执行
def show():
print("演示外部函数只执行1次")
show()
show()
show()#我们会看到仅仅输出一个外部
接下来我们创建类,并将它设计成单例模式
def singe(func):
obj = None #用来指定的flag,接收指定对象
def wrapper(*args,**kwargs):
nonlocal obj#nonlocal作用是调用外部函数的变量,不加nonlocal,Python解释器会将obj当成wrapper的局部变量。
if obj==None:#只有当对象未创建,我们才执行
#创建cls的对象
obj=func(*args,**kwargs)
return obj
return wrapper
@singe
class Account(object):
def __init__(self,name,address):
self.name = name
self.address = address
def change_address(self,new_address):
self.address = new_address
#当不是单例模式的时候,下面的account和account1i将指向两个对象,(两个地址)
account = Account("小明","北京")
account1 = Account("小明","北京")
print(id(account),id(account1))#此时,我们看到,他们地址指向相同。
#我们要更改对象名或地址,通过方法来实现,当然也可已通过.name实现
account1.change_address("上海")
print(account1.address)
#再看下单例的效果
account2 = Account("小美","天津")
print(account2.name,account.address)#结果是小明 上海
方法二
通过类里的魔术方法__new__来设置单例
我们产生一个新对象,包括创建对象和初始化对象两个步骤,在Python中:
创建对象是由__new__方法来完成的,
初始化对象是由__init__方法完成的.
所以呢,利用__new__,使得类只有第一次调用的时候才会执行,
class Account(object):
__obj = None
def __new__(cls,*args,**kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls)
return cls.__obj
def __init__(self,name,address):
self.name = name
self.address = address
account1 = Account("小明","上海")
account2 = Account("小明","上海")
print(id(account1),id(accoount2))#两个变量指向的内存地址相同,所以我们用account
乾隆皇帝弘历和和珅、纪晓岚微服私访