什么是单例
单例是指的是单个实例,指一个类只能有一个实例对象
为什么要用单例
当一个类的所有对象属性全部相同时,则没有必要创建多个对象
例如开发一个音乐播放器程序,音乐播放器可以封装为一个对象,那你考虑一下,当你切歌的时候,是重新创建一个播放器,还是使用已有的播放器?
因为播放器中的数据和业务逻辑都是相同的没有必要创建新的,所以最好使用单例模式,以节省资源
当两个对象的数据完全相同时 则没有必要占用两份资源
一、基于元类
class MymetaClass(type):
def __call__(self, *args, **kwargs):
if not hasattr(self,'instance'):
self.instance = super().__call__(*args,**kwargs)
return self.instance
class Mysql(metaclass=MymetaClass):
def __init__(self,host,port):
self.host = host
self.port = port
obj = Mysql('ajdak',213)
obj1 = Mysql('asdasdas',134234)
print(id((obj)))print(id((obj1)))print(obj.host,obj.port)print(obj1.host,obj1.port)'''3175545631755456ajdak 213ajdak 213'''
# 单例n元类
class Single(type):
def __call__(self, *args, **kwargs):
if hasattr(self,"obj"): #判断是否存在已经有的对象
return getattr(self,"obj") # 有就返回
obj = super().__call__(*args,**kwargs) # 没有则创建
print("new 了")
self.obj = obj # 并存入类中
return obj
class Student(metaclass=Single):
def __init__(self,name):
self.name = name
# 只会创建一个对象
a=Student('tank')
b=Student('tank666')
print(id(a))
print(id(b))
print(a.name)
print(b.name)
'''
new 了
31952400
31952400
tank
tank
'''
二、基于__new__
class Mysql(object):
_instance = None
def __init__(self,name):
self.name = name
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls)
return cls._instance
obj = Mysql('egon')
obj1 = Mysql('jason')
print(id(obj),id(obj1))
print(obj.name)
print(obj1.name)
'''
35619896 35619896
jason
jason
'''
三、基于classmethod
class Mysql(object):
_instance = None
def __init__(self, ip, port):
self.ip = ip
self.port = port
@classmethod
def singleton(cls):
if not cls._instance:
cls._instance = Mysql('127.0.0.1', 3306)
return cls._instance
obj1 = Mysql.singleton()
obj2 = Mysql.singleton()
print(id(obj1))
print(id(obj2))
3555452835554528
四、基于装饰器
#不传参就单例,传参就实例化新的def singleton(cls):
# 该对象在类Mysql被装饰上singleton的时候就已经实例化完毕
_instance = cls('127.0.0.1',3306)
def inner(*args,**kwargs):
# 判断是否传入参数,传入参数表示要实例化新的,不传表示用默认的
if args or kwargs:
obj = cls(*args,**kwargs)
return obj
return _instance
return inner
@singleton
class Mysql:
def __init__(self,ip,port):
self.ip = ip
self.port = port
obj1 = Mysql()
obj2 = Mysql()
obj3 = Mysql('127127127127',6666)
print(id(obj1),id(obj2))
print(id(obj3))
print(obj1.ip,obj1.port)
print(obj2.ip,obj2.port)
print(obj3.ip,obj3.port)
'''
32017096 32017096
32017656
127.0.0.1 3306
127.0.0.1 3306
127127127127 6666
'''
五、基于模块
# 单独在一个py文件中定义一个类,并实例化一个对象,之后在其他文件导入这一对象,实现单例
class Singleton(object):
def __init__(self,host,port):
self.host = host
self.port = port
singleton = Singleton('127.0.0.1',3306)