前言
#单例模式是指让一个类只能创建出唯一的实例,下面用装饰器和元类这两种方式来实现单例模式,因为这两种方式的通用性最强。
一.利用装饰器实现单例模式
创建一个字典,类名设为键,类的实例设为键的值。每次创建实例时,都会先看是否有实例存在,存在实例就直接返回该实例即可。
def singleton(cls):
# 生成一个空字典
instance = {}
# judge函数判断是否有实例存在,有:返回该实例 。无:创建实例并加入到字典
# cls是实例名,cls()是创建实例
def judge():
if cls not in instance:
instance[cls] = cls()
print(cls) #输出实例名
return instance[cls] #返回该实例
return judge #装饰器最后返回该函数
@singleton #装饰器的核心就是将函数作为参数传入另一个函数 singleton(ceshi)
class ceshi():
def __init__(self):
pass
p1 = ceshi()
p2 = ceshi()
p3 = ceshi()
print(id(p1),id(p2),id(p3)) #查看所有实例的id
#>>> <class '__main__.ceshi'>
#>>> 1298494399496 1298494399496 1298494399496
当然你也可以不用字典来接收,大可以用一个值来接受类的实例
def singleton(cls):
# 把类的实例
instance = cls()
# judge函数判断是否有实例存在,有:返回该实例 。无:创建实例并加入到字典
# cls是实例名,cls()是创建实例
def judge():
return instance #返回该实例
return judge #装饰器最后返回该函数
@singleton #装饰器的核心就是将函数作为参数传入另一个函数 singleton(ceshi)
class ceshi():
def __init__(self):
pass
p1 = ceshi()
p2 = ceshi()
p3 = ceshi()
print(id(p1),id(p2),id(p3)) #查看所有实例的id
#>>> 2049299719176 2049299719176 2049299719176
如果生成一个连接数据库的类,可以给类传入参数
def singleton(cls):
# 生成一个默认实例
instance = cls('127.0.0.1','3306')
# cls是实例名,cls()是创建实例
def judge(*args,**kwargs):
if args or kwargs:
return cls(*args,**kwargs) #传入新参数就生成新实例
return instance #没有新参数就返回默认实例
return judge #装饰器最后返回该函数
@singleton #装饰器的核心就是将函数作为参数传入另一个函数 singleton(Mysql)
class Mysql():
def __init__(self,host,port):
self.host = host
self.port = port
# 默认生成的都是一个内存地址
p1 = Mysql()
p2 = Mysql()
p3 = Mysql()
print(id(p1),id(p2),id(p3)) #查看所有实例的id 2436617218376 2436617218376 2436617218376
# 加入参数的内存地址不相同
a1 = Mysql('1.1.1.1', '1111')
a2 = Mysql('1.1.1.1', '2222')
print(id(a1),id(a2)) #2436617218504 2436617218440