单例

旧巷老猫 提交于 2019-11-28 15:39:28

什么是单例

单例是指的是单个实例,指一个类只能有一个实例对象

为什么要用单例

当一个类的所有对象属性全部相同时,则没有必要创建多个对象

例如开发一个音乐播放器程序,音乐播放器可以封装为一个对象,那你考虑一下,当你切歌的时候,是重新创建一个播放器,还是使用已有的播放器?

因为播放器中的数据和业务逻辑都是相同的没有必要创建新的,所以最好使用单例模式,以节省资源

当两个对象的数据完全相同时 则没有必要占用两份资源

一、基于元类

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)

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!