06-3 单例
什么是单例
单例是指的是单个实例,指一个类只能有一个实例对象
为什么要用单例
当一个类的所有对象属性全部相同时,则没有必要创建多个对象
例如开发一个音乐播放器程序,音乐播放器可以封装为一个对象,那你考虑一下,当你切歌的时候,是重新创建一个播放器,还是使用已有的播放器?
因为播放器中的数据和业务逻辑都是相同的没有必要创建新的,所以最好使用单例模式,以节省资源
当两个对象的数据完全相同时 则没有必要占用两份资源
一、基于元类
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)
'''
31755456
31755456
ajdak 213
ajdak 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))
35554528
35554528
四、基于装饰器
#不传参就单例,传参就实例化新的
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)