单例模式
简介:
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
例如:服务器程序的配置信息存放在一个文件中,客户端通过一个 Config 的类来读取配置文件的信息。当有很多地方都需要使用配置文件的内容时就需要创建 创建多个Config 对象的实例,从而浪费内存资源,尤其是在配置文件内容很多的情况下。
列举几种实现单例的方法:
1、使用import调用模块:
Python 的模块就是天然的单例模式,当模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,不再次执行模块代码。所以将相关的函数和数据定义在一个模块中,可以获得一个单例对象。
比如:创建一个py文件sing,写一个SingOK类,在类里创建一个func方法,并实例化一个singleton对象(必须,因为如果你再另一个模块调用的是SingOK这个类然后再实例化对象,就不是单例模式了),在另一个py文件中调用如下:
from SingOK import singleton
singleton.func()
# 查看是否是单例, 两个变量指向同一个地址
a = singleton
b = singleton
print(id(a))
print(id(b))
2.使用装饰器:
通过装饰器,将创建的类在实例化的时候只使用同一个类第一次实例化的结果。之后相同的类只取字典instances中的实例。
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def _singleton(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return _singleton
注意:网上有下面这种写法,是由于对于装饰器理解不透彻导致,这样做是可以使用同一个实例。但是对于传参的类,实例化的时候会报错的。原因是内部的函数_singleton并没有形参,应该将singleton的形参放到_singleton来。
from functools import wraps
def singleton(cls, *args, **kwargs):
instances = {}
@wraps(cls)
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return _singleton
测试上面的注意事项的代码:
@singleton
class sg:
def __init__(self, id):
self.id = id
def name(self):
print('name')
a = sg('23')
b = sg('45')
a.name()
print(id(a))
print(id(b))
3.使用__new__()方法
python类中的__new__()方法是真正创建一个实例的方法,每创建一个实例的时候都会先调用它去new一个实例对象。重写类中的__new__()方法使之成为单例。
class Tools(object):
instance = None
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super(Tools, cls).__new__(cls)
return cls.instance
或者:
class Tools(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(Tools, cls).__new__(cls)
return cls.instance