写在前面:
之前只是泛泛地理解,单例模式,趁着有些遗忘,再次深入理解下单例模式。顺便再赚点积分。
什么是单例模式?
单例模式是最简单的设计模式之一,属于创建型模式,它提供了一种创建对象的方式,确保只有单个对象被创建。这个设计模式主要目的是想在整个系统中只能出现类的一个实例,即一个类只有一个对象。 单例模式的解决的痛点就是节约资源,节省时间从两个方面看:
1.由于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级的对象而言,是很重要的.
2.因为不需要频繁创建对象,我们的GC压力也减轻了,而在GC中会有STW(stop the world),从这一方面也节约了GC的时间 单例模式的缺点:简单的单例模式设计开发都比较简单,但是复杂的单例模式需要考虑线程安全等并发问题,引入了部分复杂度。(GC垃圾回收)
简单来说,就是让你不管怎么实例化, 实例化几个,实际实际上都是对一个类操作,这跟多态是是互斥的,优点呢?就是节省资源和时间
应用场景:
- 资源共享下,避免由于资源操作时导致地性能损耗。
- 控制资源情况下, 方便资源之间的相互通信
下面介绍几种python实现单例的方法:
一 常规操作,利用__new__()
可以看到,无论实例化几次,都指向一个类, 每个实例都可以增加属性,实例可以拿到别的实例设置的属性。
class A(object):
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls)
return cls._instance
else:
return cls._instance
obj = A()
obj1 = A()
obj2 = A()
obj.attr = 'value'
obj2.attrs = 'lala'
obj1.attr = 'value1'
print(obj.attr) # value1
print(obj1.attr) # value1
print(obj2.attr) # value1
print(obj2.attrs) # lala
print(obj is obj1) # True
非单例对比, 体现了python的多态。
class A(object):
pass
obj = A()
obj1 = A()
obj2 = A()
obj.attr = 'value'
obj2.attrs = 'lala'
obj1.attr = 'value1'
print(obj.attr) # value
print(obj1.attr) # value1
# print(obj2.attr) # 直接报错,是我A没有attr属性
print(obj2.attrs) # lala
print(obj is obj1) # False
二 利用python天生的特性
python天生就支持单例模式(生来就有,这让人很无奈啊)
python模块,就是天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,,就会直接加载.pyc文件,而不会再执行模块代码。所以只要把相关的函数和数据定义子一个模块中,就可以获得一个单例对象了。
其实我觉这种方法,太直白了,或者说直白的让人疑惑。就是你在py文件中写个类, 给它实例化一个实例,别的文件引用这个实例,,
确保一个类只有一个实例对象,,,
# myclass.py
class A(object):
pass
obj = A()
# 在别的文件中引入
from myclass import obj
obj.attr = "lala"
三 根据装饰器
就是定义个空字典,字典没有这个类,就加进去,有的话,直接返回会原来的类
def single(cls):
_instance = {}
def getinstance(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return getinstance
@single
class A(object):
a = 1
obj = A()
obj1 = A()
obj.attr = "lal"
print(obj1.attr) # lal
print(obj is obj1) # True
四 使用metaclss(元类), 这个就很哲学了,从元类开始操作
要做到:
- 拦截类的创建
- 修改类的定义
- 返回修改后的类
class Single(type):
def __init__(self, *args, **kwargs):
self._instance = None
super(Single, self).__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
# 这里的cls,即A类
if cls._instance is None:
cls._instance = super(Single, cls).__call__(*args, **kwargs)
return cls._instance
class A(metaclass=Single):
pass
obj = A()
obj1 = A()
obj.attr = "lal"
print(obj1.attr) # lal
print(obj is obj1) # True