一、什么是单例模式
故事:你是我的唯一
假期总是短暂的,李力和女朋友要分开了。在车站的站台上,李力深情的看着女朋友说,“你是我此生的唯一”
1.1用程序模拟生活
我们都希望爱情里我们是彼此的唯一,程序如人生,有些类我们也希望它只有一个实例。
class MyBeautifulGril:
__instance = None
__isFirstInit = False
def __new__(cls, *args, **kwargs):
if not cls.__instance:
MyBeautifulGril.__instance = super().__new__(cls)
return cls.__instance
def __init__(self, name):
if not self.__isFirstInit:
self.__name = name
print("遇见" + name + ", 我一见钟情!")
MyBeautifulGril.__isFirstInit = True
else:
print("遇见" + name + ", 我置若惘闻!")
def showMyHeart(self):
print(self.__name + "就是我心中的唯一!")
def TestLove():
jenny = MyBeautifulGril("Jenny")
jenny.showMyHeart()
kimi = MyBeautifulGril("kimi")
kimi.showMyHeart()
print("id(jenny):", id(jenny), "id(kimi):", id(kimi))
if __name__ == "__main__":
TestLove()
输出结果:
遇见Jenny, 我一见钟情!
Jenny就是我心中的唯一!
遇见kimi, 我置若惘闻!
Jenny就是我心中的唯一!
id(jenny): 4326687312 id(kimi): 4326687312
二、单例模式的定义
2.1定义
确保一个类只有一个实例,并且提供一个访问它的全局方法。
单例模式就是保证一个类有且只有一个对象(实例)的一种机制。单例模式用来控制某些事物只允许有一个个体。
三、单例模式的模型抽象
3.1单例模式的实现方式有很多种,下面列出几种常见的方式。
(1)、重写__new__和__init__方法
class Singleton1:
"""单例模式实现方式"""
__instance = None
__isFirstInit = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
Singleton1.__instance = super().__new__(cls)
return cls.__instance
def __init__(self, name):
if not self.__isFirstInit:
self.__name = name
Singleton1.__isFirstInit = True
def getName(self):
return self.__name
def testfunc():
tony = Singleton1("Tony")
karry = Singleton1("Karry")
print(tony.getName(), karry.getName())
print("id(tony):", id(tony), "id(karry):", id(karry))
print("tony is karry:", tony is karry)
if __name__ == "__main__":
testfunc()
输出结果:
Tony Tony
id(tony): 4351308368 id(karry): 4351308368
tony is karry: True
在Python3的类中,__new__负责对象的创建,而__init__负责对象的初始化:__new__是一个类方法,而__init__是一个对象方法。
__new__是我们通过类名进行实例化对象时自动调用的,__init__是在每一次实例化对象后调用的,__new__方法创建一个实例之后返回这个实例的对象,并将其传递给__init__方法的self参数。
在上面的实例代码中,当调用__new__时,我们会传递类对象给cls参数,我们定义一个静态的__instance类变量,用来存放Singleton1的对象,__new__方法每次返回同一个__instance对象(若未初始化,则进行初始化)。因为每一次通过s= Singleton1()的方式创建对象时,都会自动调用__init__方法来初始化实例对象,因此__isFirstInit的作用就是确保只对__instance对象进行一次初始化。
(2)、自定义metaclass的方法
class Singleton2(type):
"""单例模式实现方式二"""
def __init__(cls, what, bases=None, dict=None):
super().__init__(what, bases, dict)
cls.__instance = None # 初始化全局变量cls.__instance为None
def __call__(cls, *args, **kwargs):
"""控制对象的创建过程,如果cls.__instance为None,则创建,否则直接返回"""
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
class CustomClass(metaclass=Singleton2):
"""用户自定义的类"""
def __init__(self, name):
self.__name = None
def getName(self):
return self.__name
if __name__ == "__main__":
tony = CustomClass("Tony")
karry = CustomClass("karry")
print(tony.getName(), karry.getName())
print("id(tony):", id(tony), "id(karry):", id(karry))
print("tony == karry:", tony == karry)
输出结果:
Tony Tony
id(tony): 4507292144 id(karry): 4507292144
tony == karry: True
(3)、装饰器的方法
def singletonDecorator(cls, *args, **kwargs):
"""定义一个单例装饰器"""
instance = {}
def wrapperSingleton(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return wrapperSingleton
@singletonDecorator
class Singleton3:
"""使用单例装饰器修饰一个类"""
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
if __name__ == "__main__":
tony = Singleton3("Tony")
karry = Singleton3("karry")
print(tony.getName(), karry.getName())
print("id(tony):", id(tony), "id(karry):", id(karry))
print("tony == karry:", tony == karry)
输出结果:
Tony Tony
id(tony): 4313830736 id(karry): 4313830736
tony == karry: True
装饰器的实质就是对传进来的参数进行补充,可以在不对原有的类做任何代码变动的前提下增加额外的功能,使用装饰器可以装饰多个类。用装饰器的方式来实现单例模式,通用性非常高,在实际项目中用的非常多。
四、基于框架的实现
4.1基于上面的方式三装饰器的方式实现单例模式
from singleton3 import singletonDecorator
@singletonDecorator
class MyBeautifulGril:
def __init__(self, name):
self.__name = name
if self.__name == name:
print("遇见" + name + ", 我一见钟情!")
else:
print("遇见" + name + ", 我置若罔闻!")
def showMyHeart(self):
print(self.__name + "就是我心中的唯一!")
def TestLove():
jenny = MyBeautifulGril("Jenny")
jenny.showMyHeart()
kimi = MyBeautifulGril("kimi")
kimi.showMyHeart()
print("id(jenny):", id(jenny), "id(kimi):", id(kimi))
if __name__ == "__main__":
TestLove()
输出结果:
遇见Jenny, 我一见钟情!
Jenny就是我心中的唯一!
Jenny就是我心中的唯一!
id(jenny): 4414658400 id(kimi): 4414658400
4.2 应用场景
(1)确保一个类有且只有一个实例
(2)项目中的一些全局管理类(Manager)可以用单例模式来实现。
网友评论