单例模式的5种实现方式
[1 使用模块](#1 使用模块)
[2 使用装饰器](#2 使用装饰器)
[3 使用类方法](#3 使用类方法)
4.基于new方法实现
[5 基于metaclass方式实现](#5 基于metaclass方式实现)
单例模式的5种实现方式
python
什么是单例模式?
单例模式是指:保证一个类仅有一个实例,并提供一个访问它的全局访问点
# 线程1 执行:
cursor.excute('select * from user')
# 线程2执行
cursor.excute('select * from books')
# 线程1 执行
cursor.fetchAll() # 拿出查询到的数据
# django ,每个线程,一个连接对象---》 连接池
1 使用模块
python
其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当
第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
如果我们真的想要一个单例类,可以考虑这样做:
1.新建一个mysingleton.py
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
2.将上面的代码保存在文件 mysingleton.py 中,要使用时,直接在其他文件中导入此文件中的对象,
这个对象即是单例模式的对象:
from a import singleton
2 使用装饰器
python
def Singleton(cls):
instance = None
def _singleton(*args, **kargs):
nonlocal instance
if not instance:
instance = cls(*args, **kargs)
return instance
return _singleton
@Singleton
class A(object):
def __init__(self, x=0):
self.x = x
a1 = A(2)
a2 = A(3)
print(a1.x)
print(a2.x)
print(a1 is a2) # True
回顾装饰器是什么
python
import time
# 装饰器是什么?装饰器的作用是什么?
'''
装饰器是闭包函数的一个典型应用
它是什么?
在不改变函数源代码和调用方式idea基础上,为函数增加新功能
'''
# def add(a, b):
# time.sleep(2)
# return a + b
def time_total(func):
def inner(a, b):
start = time.time()
res = func(a, b)
print('运行时间是:', time.time() - start)
return res
return inner
# add = time_total(add)
# res = add(3, 4)
# print(res)
@time_total # 原理就是 add=time_total(add)
def add(a, b):
time.sleep(2)
return a + b
res = add(3, 4)
print(res)
print(add.__name__) # 就是inner
# 什么是闭包函数?参数不是传进来的,是用了它上一层作用域范围的变量
'''
1 定义在函数内部
2 对外部作用域有引用(如果使用外部的可变类型,则直接使用;
如果是不可变类型,需要使用nonlocal)
例如:
def add():
a = 10
def inner():
nonlocal a
a += 1
print('闭包内部的值是:', a) # 11
inner()
print('闭包外部的值是:', a) # 11
add()
'''
3 使用类方法
python
class Singleton(object):
_instance=None
def __init__(self):
pass
@classmethod
def instance(cls, *args, **kwargs):
if not cls._instance:
cls._instance=cls(*args, **kwargs)
return cls._instance
a1=Singleton.instance()
a2=Singleton().instance()
print(a1 is a2)
4 基于new方法实现
python
class Singleton(object):
_instance=None
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls)
return cls._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)
5 基于metaclass方式实现
python
# 产生类这个对象的类,称之为元类
# 类中的 __call__什么时候回触发?对象()会触发
class SingletonType(type):
_instance = None
def __call__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls)
cls._instance.__init__(*args, **kwargs)
return cls._instance
class Foo(metaclass=SingletonType):
def __init__(self, name):
self.name = name
obj1 = Foo('name')
obj2 = Foo('name')
print(obj1.name)
print(obj1 is obj2) # True
# __init__ 和 __new__ 区别是什么?
# 1 类()--->触发类中的__init__---->对象已经创建出来了,不能拦截住,做成单例了
# 2 类()----》触发类中的__new__----》真正的创建对象,判断之前有没有创建过,如果创建过,直接返回
# 3元类---》类()--->触发元类的__call__---》判断之前有没有创建过,如果有,直接返回