1.什么是单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。单例模式能控制一个类只能产生一个对象。
2.为什么需要单例模式
- 当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
- 当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。
3.单例模式应用场景
- Python的logger就是一个单例模式,用以日志记录
- Windows的资源管理器是一个单例模式
- 线程池,数据库连接池等资源池一般也用单例模式
- 网站计数器
4.在 Python 中,实现单例模式的四种方式:
- 使用模块
- 使用装饰器(decorator)
- 使用 __new__
- 使用元类
4.1 使用模块
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
如果我们真的想要一个单例类,可以考虑这样做:
# mysingleton.py class My_Singleton(object): def foo(self): pass my_singleton = My_Singleton()
将上面的代码保存在文件 mysingleton.py 中,然后这样使用:
from mysingleton import my_singleton my_singleton.foo()
4.2 使用装饰器
装饰器维护一个字典对象instances,缓存了所有单例类,只要单例不存在则创建,已经存在直接返回该实例对象。
我们定义一个装饰器 singleton,它返回了一个内部函数 wrapper,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。
使用装饰器实现单例模式的代码如下:
def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class Foo(object): pass
4.3 使用__new__
__new__方法: __new__()方法用于定义创建对象时执行的操作
object类中的__new__()方法完成对象创建过程中的内存空间申请,对象属性初始化等一系列的操作。__new__是真正创建实例对象时用到的方法,所以重写基类的__new__方法,以此来保证创建对象的时候只生成一个实例。
注意事项:
1.__new__()方法创建对象时自动运行。
2.覆盖object类中的__new__方法后创建对象 将执行覆盖后的方法。
注意事项:
__new__()方法仅仅是python开放出来给用户干预创建对象时的一个操作入口,该方法并不是直接完成分配内存、创建对象的操作,创建对象的操作由python底层统一管理。
使用__new__方法实现单例模式的代码如下:
class Singleton(object): _instance = None def __new__(cls, *args, **kw): if not cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) return cls._instance class MyClass(Singleton): pass foo1 = MyClass() foo2 = MyClass() print(foo1) print(foo2)
4.4 使用元类
元类是用于创建类对象的类,类对象创建实例对象时一定会调用__call__方法,因此在调用__call__时候保证始终只创建一个实例即可,type是python中的一个元类。
元类(metaclass)可以控制类的创建过程,它主要做三件事:
拦截类的创建
修改类的定义
返回修改后的类
使用元类实现单例模式的代码如下:
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] # Python2 # class MyClass(object): # __metaclass__ = Singleton # Python3 class MyClass(metaclass=Singleton): pass foo1 = MyClass() foo2 = MyClass() print(foo1) print(foo2)
原文地址:https://www.cnblogs.com/new-rain/p/10023473.html