所谓单例模式,就是指一个实例对象只产生一次
创建唯一的一个实例对象。
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了
【单例模式优缺点】
【优点】
一、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
二、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
【缺点】
一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用
单例模式的简单理解:
1 单例模式 只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。
2 单例的缺点 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
用单例模式,就是在适用其优点的状态下使用 。
"""
单例模式特别像中国的婚姻法:
一夫一妻制
如果需要结婚,必须到民政局登记
民政局 检测两个人的户口本 看上面的结婚状态
已婚 不予登记
未婚 给予登记
那么按照这个思路实现python中的单例模式
1.需要一个方法,可以去控制当前对象的创建过程
__new__
2.需要一个标识来存储和表示是否有对象
创建一个私有属性进行存储,默认值为None
3.在创建对象的方法中去检测和判断是否有对象?
如果没有对象,则创建对象,并把对象存储起来,返回对象
如果存储的是对象,则直接返回对象,就不需要创建新的对象了
"""
# class Danli():
# obj = 1
# def __new__(cls, *args, **kwargs):
# print(*args)
# return cls
#
#
# d = Danli()
# print(d)#<class '__main__.Danli'>
class Danli():
#2.定义私有属性,存储对象,默认值为None
__obj = None
#1.定义构造方法
def __new__(cls, *args, **kwargs):
#3.在创建对象的过程中,判断是否有对象
if not cls.__obj:
#判断如果没有对象,则创建对象,并且存储起来
cls.__obj = object.__new__(cls)
#直接把存储的对象返回
return cls.__obj
#实例化对象,返回的是同一个内存地址
d1 = Danli()
print(d1)#<__main__.Danli object at 0x000001FA3E4528D0>
d2 = Danli()
print(d2)#<__main__.Danli object at 0x000001D970591940>
d3 = Danli()
print(d3)#<__main__.Danli object at 0x000001D970591940>
案例:
from typing import Any
class Car:
#声明实例对象未创建为None
instance = None #类属性
#控制实例变量的属性,默认是未被赋予属性
isCreate = False
def __new__(cls,brand,color,wheel):
if Car.instance == None:
#创建实例对象
Car.instance = super().__new__(cls)
return Car.instance
# #返回的是创建实例对象的内存地址
# x = super().__new__(cls)
# print(x)
# return x
def __init__(self,brand,color,wheel):
if Car.isCreate == False:
self.brand = brand
self.color = color
self.wheel = wheel
Car.isCreate = True
def show(self):
print(self.brand,self.color,self.wheel)
#创建类的实例对象
c1 = Car("五菱宏光","粉色",4)
print(id(c1))
c1.show()
c2 = Car("拖拉机","黄金色",4)
c2.show()
print(id(c2))
c3 = Car("路虎","白色",4)
print(id(c3))
c3.show()
输出结果:
2033404387168
五菱宏光 粉色 4
五菱宏光 粉色 4
2033404387168
2033404387168
五菱宏光 粉色 4
# class D:
# # #在类里 快捷键 Ctrl+o 快速生成(Select Methods to override)选择重写或实现方法
# # def __new__(cls) -> Any:
# # return super().__new__(cls)