单例模式
目录1 单例模式简介
- 一个类是一个类只有单个对象被创建,只能有一个实例;
- 自己创建这个实例;
- 整个系统都要使用这个实例。
1.1 为什么需要单例模式
对于有一些对象,其实例我们只需要一个,比方说:线程池、缓存(cache)、日志对象等,如果创建多个实例,就会导致许多问题产生,比如资源使用过量、程序行为不可控,或者导致不一致的结果。如:产生了很多实例,而它们做的事情只是执行发一个邮件的功能。这会特别浪费内存资源,因为频繁创建和销毁实例。
单例追求的目标:
- 线程安全。
- 懒加载:延迟加载 (懒加载)是一种将资源标识为非阻塞(非关键)资源并仅在需要时加载它们的策略。 。
- 调用效率高。
1.2 单例模式的基本构造
- 私有的构造方法
- 私有的、静态的实例化变量应用
- 提供一个公有的、静态的获取类实例对象方法
2 代码层面理解单例模式
2.1 多例模式
- 多例模式是一个类可以有多个对象被创建
# 多例模式
class Singleon1():
def __init__(self, name):
self.name = name
sin01 = Singleon1("xxx")
sin02 = Singleon1("xxx")
print(sin01)
# <__main__.Singleon1 object at 0x000001FAD4DD3DF0>
print(sin02)
# <__main__.Singleon1 object at 0x000001FAD4B62EF0>
2.2 单例模式创建
2.2.1 正常情况下的单例模式
# 单例模式
class Singleon1(object):
instance = None # 静态字段、类变量
def __new__(cls, *args, **kwargs): # cls指代当前类
"""
创建对象
__new__方法一定要返回一个实例对象,才会执行后面的__init__方法;
在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。
:param args:
:param kwargs:
"""
if not cls.instance:
# cls.instance = object.__new__(cls) # 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object
# cls.instance = super().__new__(cls) # super().__new__(cls) super()方法返回的即是object对象
cls.instance = super(Singleon1, cls).__new__(cls) # super实际传入了两个参数,第一个是本类的类型(Singleon1),第二个是类型(cls),cls即父类的类
# cls.instance = Singleon1.__new__(cls) # 不可调用自身的__new__方法,这样会因为执行自己的__new__()方法,造成死循环,
return cls.instance
def __init__(self, name):
"""
初始化对象
:param name:
"""
self.name = name
sin01 = Singleon1("xxx")
sin02 = Singleon1("xxx")
print(sin01)
# <__main__.Singleon1 object at 0x000001B4524F7C40>
print(sin02)
# <__main__.Singleon1 object at 0x000001B4524F7C40>
2.2.2 threading与time下的的单例模式
-
如果直接threading直接调用单例,产生异常。
import threading import time # 单例模式 class Singleon1(object): instance = None # 静态字段、类变量 def __new__(cls, *args, **kwargs): # cls指代当前类 """ 创建对象 __new__方法一定要返回一个实例对象,才会执行后面的__init__方法; 在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。 :param args: :param kwargs: """ if not cls.instance: time.sleep(1) # cls.instance = object.__new__(cls) # 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object # cls.instance = super().__new__(cls) # super().__new__(cls) super()方法返回的即是object对象 cls.instance = super(Singleon1, cls).__new__(cls) # super实际传入了两个参数,第一个是本类的类型(Singleon1),第二个是类型(cls),cls即父类的类 # cls.instance = Singleon1.__new__(cls) # 不可调用自身的__new__方法,这样会因为执行自己的__new__()方法,造成死循环, return cls.instance def __init__(self, name): """ 初始化对象 :param name: """ self.name = name def func(): obj = Singleon1("xxx") print(obj) for i in range(10): task = threading.Thread(target=func) task.start() # <__main__.Singleon1 object at 0x0000017B7E5A2170> # <__main__.Singleon1 object at 0x0000017B7E7A3460> # <__main__.Singleon1 object at 0x0000017B7E5A2170> # <__main__.Singleon1 object at 0x0000017B7E7A3B20> # <__main__.Singleon1 object at 0x0000017B7E7A3EE0> # <__main__.Singleon1 object at 0x0000017B7E5A2170> # <__main__.Singleon1 object at 0x0000017B7E7A3B20> # <__main__.Singleon1 object at 0x0000017B7E7E9B40> # <__main__.Singleon1 object at 0x0000017B7E5A2170> # <__main__.Singleon1 object at 0x0000017B7E7A3460>
-
需要对使用单例模式的类进行加锁
import threading import time # 单例模式 class Singleon1(object): instance = None # 静态字段、类变量 rlock = threading.RLock() def __new__(cls, *args, **kwargs): # cls指代当前类 """ 创建对象 __new__方法一定要返回一个实例对象,才会执行后面的__init__方法; 在类的继承中,__init__方法里,我们通常写的是super(类名,self),而这里是super(类名,cls),从self变成cls的原因是,要调用父类的__new__方法,这时还没有对象实例产生。 :param args: :param kwargs: """ if cls.instance: return cls.instance with cls.rlock: if not cls.instance: time.sleep(1) cls.instance = object.__new__(cls) # 默认调用父类的__new__()方法来创建实例,python中所有的类都继承object # cls.instance = super().__new__(cls) # super().__new__(cls) super()方法返回的即是object对象 # cls.instance = super(Singleon1, cls).__new__(cls) # super实际传入了两个参数,第一个是本类的类型(Singleon1),第二个是类型(cls),cls即父类的类 # cls.instance = Singleon1.__new__(cls) # 不可调用自身的__new__方法,这样会因为执行自己的__new__()方法,造成死循环, return cls.instance def __init__(self, name): """ 初始化对象 :param name: """ self.name = name def func(): obj = Singleon1("xxx") print(obj) for i in range(10): task = threading.Thread(target=func) task.start() # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170> # <__main__.Singleon1 object at 0x0000024392DA2170>
-
或使用模块引用方式
Singleon2_test.py # 单例模式 class Singleon2(object): pass obj = Singleon2() test.py from Singleon2_test import obj if __name__ == '__main__': print(obj) print(obj) print(obj) print(obj) # <Singleon2_test.Singleon2 object at 0x000002C645007C40> # <Singleon2_test.Singleon2 object at 0x000002C645007C40> # <Singleon2_test.Singleon2 object at 0x000002C645007C40> # <Singleon2_test.Singleon2 object at 0x000002C645007C40>