单例模式
简介
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。 当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
优点
- 对唯一实例的受控访问
- 单利相当于全局变量,但防止了命名空间被污染
- 对唯一实例的受控访问 单利相当于全局变量,但防止了命名空间被污染 与单利模式功能相似的概念:全局变量、静态变量(方法)
缺点
- 虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
- 使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类
- 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致单例类中出现悬浮引用。
单利实现方式
基于__new__实现
- 实现__new__方法,然后将类的一个实例绑定到类变量_instance上
- 如果cls._instance为None,则说明该类还没有被实例化过,new一个该类的实例,并返回
- 如果cls._instance不为None,直接返回_instance
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'): # 判断是否有_instance属性
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
return cls._instance
name = 'SR'
s1 = Singleton()
s2 = Singleton()
print(s1.name) # SR
print(s2.name) # SR
print(id(s1)) # 140368628557584
print(id(s2)) # 140368628557584
print(s1 == s2) # True
print(s1 is s2) # True
使用元类实现
本质上是方法一的升级版,使用metaclass(元类)的python高级用法,具体代码如下
"""
class Singleton中的__init__在Myclass声明的时候被执行Myclass=Singleton()
Myclass()执行时,最先执行父类的__call__方法(object,Singleton都作为Myclass的父类,
根据深度优先算法,会执行Singleton中的__call__(),Singleton中的__call__()写了单例模式)
"""
class Singleton(type):
def __init__(self, name, bases, dict):
super(Singleton,self).__init__(name,bases, dict)
self._instance = None
def __call__(self, *args, **kwargs):
if self._instance is None:
self._instance = super(Singleton,self).__call__(*args, **kwargs)
return self._instance
class MyClass(object,metaclass=Singleton):
a = 1
one=MyClass()
two=MyClass()
print(id(one)) # 1553247294800
print(id(two)) # 1553247294800
print(one == two) # True
print(one is two) # True
装饰器
def singleton(cls, *args, **kwargs):
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return _singleton
@singleton
class MyClass3(object):
a = 1
one = MyClass3()
two = MyClass3()
print(id(one)) # 140383866774528
print(id(two)) # 140383866774528
print(one == two) # True
print(one is two) # True
基于new方法
python的单例模式__new__()在__init__()之前被调用,用于生产实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。单例模式是指创建唯一对象,单例模式设计的类只能实例化一个对象。
class Singleton(object):
__instance=None
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if Singleton.__instance is None:
Singleton.__instance=object.__new__(cls,*args, **kwargs)
return Singleton.__instance
one=Singleton()
two=Singleton()
print(id(one)) # 2488569943376
print(id(two)) # 2488569943376
print(one == two) # True
print(one is two) # True