【一】单例模式概念
- 单例模式是一种设计模式,其核心思想是确保一个类只有一个实例,并提供一个全局访问点。
- 单例模式通常用于管理共享的资源,例如配置信息、数据库连接、线程池等。
- 关键点在于如何判断这个类是否已经实例化
- 通过模块导入:借助模块的底层导入原理
- 通过元类实现:元类的魔法方法
__call__
会在实例化之前执行,可以进行判断 - 通过装饰器实现:装饰器也会在实例化之前操作,可以尽心判断
【二】单例模式实现方法
【1】通过模块导入
- 这是最简单并且最好理解的方法,建议就用这个
python
# module.py文件内容
class FuncTools(object):
pass
func_tools = FuncTools()
python
# 需要导入这个功能对象的文件
from module import func_tools
functools......
- 模块只会导入一次,第二次导入时在内存中找到了这个实例对象,所以就不会再次生成一个新的实例
【2】通过元类实现
- 有一点难度
python
class MyMeta(type):
__have_instance = None
def __call__(cls, *args, **kwargs):
if not cls.__have_instance:
obj = super().__call__(*args, **kwargs)
cls.__have_instance = obj
return cls.__have_instance
class Student(metaclass=MyMeta):
def __init__(self, name):
self.name = name
student_one = Student("bruce")
print(student_one.name, id(student_one))
# bruce 2973012426224
student_two = Student("tom")
print(student_two.name, id(student_two))
# bruce 2973012426224
- 在生成实例(
student_one
)的时候触发元类(MyMeta
)的__call__
方法进行判断没有实例,创建了实例 - 在生成第二个实例(
student_two
)的时候再次触发元类(MyMeta
)的__call__
方法进行判断,有了实例直接返回已经存在,所以不会创建新的实例 - 为什么是用的元类(
MyMeta
)的__call__
方法呢?- 因为
__init__
和__new__
都是在定义类(Student
)的时候执行的 - 仅执行了一次,并且还是在实例(
student_one
)之前触发的 - 所以只能用元类(
MyMeta
)的__call__
- 因为
【3】通过装饰器实现
- 理解难度比元类好一点
python
def singleton(cls):
cls_dict = {}
def inner(*args, **kwargs):
if cls not in cls_dict.keys():
cls_dict[cls] = cls(*args, **kwargs)
return cls_dict[cls]
return inner
@singleton
class Student(object):
def __init__(self, name):
self.name = name
student_one = Student("bruce")
print(student_one.name, id(student_one))
student_two = Student("tom")
print(student_two.name, id(student_two))
- 通过装饰器
singleton
装饰类(Student
) - 在生成第一个学生(
bruce
)时,判断没有这个类没有产生实例,所以创建了实例(student_one
) - 在生成第二个学生(
tom
)时,判断这个类已经生成过实例,所以没有创建新的,返回第一次生成的实例(student_one
)