简介:单例模式(Singleton Pattern) 是最简单的设计模式之一,属于创建型的设计模式。单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,不需要实例化该类的对象。
特性:
- 单例类只有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
优点:
- 在内存中只有一个实例,减少内存的开销,尤其是频繁的创建和销毁实例
- 避免对资源的多重占用
缺点:
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化
应用场景
- 资源共享的情况下,避免由于资源操作时导致的性能损耗等。如日志文件,应用配置
- 控制资源的情况下,方便资源之间的互相通信。如线程池等。
实现核心原理
重写类方法中的____new____方法
-
使用类名()创建对象时,Python的解释器首先会调用____new____方法为对象分配空间
-
____new____是一个由object基类提供的内置静态方法,主要作用有:1.分配内存为对象分配空间;2.返回对象的引用
-
Python的解释器获得对象的引用后,将引用作为第一个参数,传递给____init____方法
代码示例
-
懒汉式 非线程安全的单例模式
这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁synchronized,所以严格意义上它并不算单例模式。
class Singleton(object): instance = None def __new__(cls,name,age): if not cls.instance: cls.instance = object.__new__(cls) return cls.instance test1 = Singleton("zhangsan",18) test2 = Singleton("lisi",18) print(id(test1)) print(id(test2)) test1.age = 30 print(test2.age)
运行结果:
4389937560 4389937560 30 Process finished with exit code 0
-
懒汉式 线程安全的单例
这种方式具备很好的lazy loading 能够在多线程中很好的工作,但是,效率很低,99%情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费
缺点:必须加锁synchronized 才能保证单例,但加锁会影响效率
import threading def synchronized(func): func.__lock__ = threading.Lock() def lock_func(*args, **kwargs): with func.__lock__: return func(*args, **kwargs) return lock_func class Singleton(object): instance = None @synchronized def __new__(cls): if not cls.instance: cls.instance = super(Singleton, cls).__new__(cls) return cls.instance test1 = Singleton() test2 = Singleton() print(id(test1)) print(id(test2))
运行结果:
4554555800 4554555800 Process finished with exit code 0
知识补充
Python的模块就是天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,就会直接加载.pyc文件,而不会在此执行模块代码。因此,我们只需要把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。例如:
#mysingleton.py
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
将上面的代码保存在文件mysingleton.py中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象
from xxxx import singleton
每天多努力那么一点点,积少成多
网友评论