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)
posted @ 2019-08-26 16:35  www.pu  Views(287)  Comments(0Edit  收藏  举报