当前位置: 首页 > news >正文

Python设计模式 - 单例模式

定义

单例模式是一种创建型设计模式, 其主要目的是确保一个类只有一个实例, 并提供一个全局访问点来访问该实例。

结构

在这里插入图片描述

应用场景

  1. 资源管理:当需要共享某个资源时,例如数据库连接、线程池、日志对象等,可以使用单例模式确保所有的客户端都使用同一个资源实例,从而避免资源的浪费和不一致性。
  2. 配置信息:在应用程序中,可能会有一些全局配置信息需要在各个地方被访问和使用,例如系统配置、日志配置等,这时可以使用单例模式来存储和管理这些配置信息。
  3. 缓存管理:在需要缓存数据以提高性能的场景中,可以使用单例模式来管理缓存实例,确保所有地方都使用同一个缓存对象,避免数据不一致或者缓存混乱的问题。

优缺点

优点:

  1. 资源节约:单例模式确保一个类只有一个实例存在,可以节约系统资源,避免了多次创建相同类型的对象所带来的资源浪费。
  2. 全局访问点:单例模式提供了一个全局的访问点,使得可以在任何时候、任何地方都能够访问到该实例,方便了对象的访问和使用。
  3. 实例控制:由于单例模式只能创建一个实例,因此可以对实例进行严格的控制,例如可以限制实例的数量、延迟实例化等。

缺点:

  1. 对扩展性的限制:由于单例模式创建的实例是静态的,因此很难对其进行子类化或者扩展。如果需要在单例类的基础上添加新的功能,可能需要修改现有的代码,这会增加耦合性并且破坏了开闭原则。
  2. 职责过多:单例模式在一定程度上违背了单一职责原则,因为单例类既提供了业务方法,又提供了创建对象的方法,将对象的创建和对象本身的功能耦合在一起。

Java代码示例

饿汉式

饿汉式实现是在类定义时就创建单例对象,不管是否需要使用该对象。

public class Singleton {// 在类加载时就创建好实例private static Singleton instance = new Singleton();// 私有化构造函数,防止外部实例化private Singleton() {}// 提供一个公共的静态方法返回实例public static Singleton getInstance() {return instance;}
}

懒汉式

懒汉式实现是在需要时才创建实例。

public class Singleton {// 声明一个静态的实例变量,但不初始化private static Singleton instance;// 私有化构造函数,防止外部实例化private Singleton() {}// 提供一个公共的静态方法返回实例public static Singleton getInstance() {// 检查实例是否已经被创建,如果没有,才进行实例化if (instance == null) {instance = new Singleton();}return instance;}
}

以上实现不是线程安全的,在多线程高并发访问时,要使用双重检查锁定来实现线程安全。

public class Singleton {// 声明一个 volatile 类型的静态变量,确保多线程下的可见性private static volatile Singleton instance;// 私有化构造函数,防止外部实例化private Singleton() {}// 提供一个公共的静态方法返回实例public static Singleton getInstance() {// 第一次检查,如果实例为空,则进入同步块if (instance == null) {synchronized (Singleton.class) {// 第二次检查,再次判断实例是否为空,如果为空,则创建实例if (instance == null) {instance = new Singleton();}}}return instance;}
}

静态内部类(推荐)

使用静态内部类实现单例模式是一种常见的方式,这种方法利用了类加载的特性来保证懒加载和线程安全。

public class Singleton {// 私有化构造方法,防止外部实例化private Singleton() {}// 静态内部类,用于实现懒加载和线程安全private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}// 对外提供获取单例对象的方法public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

Python代码示例

使用模块

使用模块来实现饿汉式单例模式是一种简单而有效的方法。在 Python 中导入一个模块时,解释器会确保这个模块只被加载一次,因此可以利用这一点来实现单例模式。

# singleton.py
class Singleton:pass# 创建单例实例
singleton_instance = Singleton()# main.py
from singleton import singleton_instance# 使用单例实例
singleton_instance.some_attribute = "some_value"

使用装饰器

使用装饰器可以实现懒汉式单例模式,实例在第一次被请求时才会被创建。

def singleton(cls):instances = {}def get_instance(*args, **kwargs):if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return get_instance@singleton
class Singleton:pass# 使用单例对象
singleton_instance1 = Singleton()
singleton_instance2 = Singleton()

使用类属性

使用类属性也可以实现懒汉式单例模式。

class Singleton:_instance = None  # 类属性用于存储单例实例@classmethoddef get_instance(cls, value):if not cls._instance:cls._instance = cls(value)return cls._instance# 使用单例对象
singleton_instance1 = Singleton.get_instance()
singleton_instance2 = Singleton.get_instance()

也可以通过 new 方法来实现,同样是将实例对象存储到类属性中。

class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if cls._instance is None:cls._instance = super().__new__(cls)return cls._instance# 使用单例对象
singleton_instance1 = Singleton()
singleton_instance2 = Singleton()

使用元类(推荐)

使用元类可以更加灵活地控制类的创建过程,从而实现懒汉式单例模式。

class SingletonMeta(type):_instances = {}def __call__(cls, *args, **kwargs):if cls not in cls._instances:cls._instances[cls] = super().__call__(*args, **kwargs)return cls._instances[cls]class Singleton(metaclass=SingletonMeta):pass# 使用单例对象
singleton_instance1 = Singleton()
singleton_instance2 = Singleton()

在多线程高并发访问时,要使用双重检查锁定来实现线程安全。

from threading import Lock, Threadclass SingletonMeta(type):_instances = {}_lock = Lock()def __call__(cls, *args, **kwargs):if cls not in cls._instances:with cls._lock:if cls not in cls._instances:instance = super().__call__(*args, **kwargs)cls._instances[cls] = instancereturn cls._instances[cls]class Singleton(metaclass=SingletonMeta):pass

饿汉式单例类和懒汉式单例类的比较

  1. 资源利用率:饿汉式单例类在类被加载时创建实例,无论运行时是否使用该实例;懒汉式单例类在第一次使用时创建实例;所以懒汉式单例类资源利用率更高。
  2. 线程安全问题:饿汉式单例类在类被加载时创建实例,是线程安全的;懒汉式单例类需要增加双重检查锁定来实现线程安全;

参考

《设计模式的艺术》
单例设计模式 (refactoringguru.cn)
Python中的单例模式的几种实现方式的及优化 - 听风。 - 博客园 (cnblogs.com)

相关文章:

Python设计模式 - 单例模式

定义 单例模式是一种创建型设计模式, 其主要目的是确保一个类只有一个实例, 并提供一个全局访问点来访问该实例。 结构 应用场景 资源管理:当需要共享某个资源时,例如数据库连接、线程池、日志对象等,可以使用单例模…...

AI日报:干翻AI PC!苹果M4芯片首发;GoEnhance可生成粘土风格视频;DeepSeek-V2模型已在魔搭社区开源

欢迎来到【AI日报】栏目!这里是你每天探索人工智能世界的指南,每天我们为你呈现AI领域的热点内容,聚焦开发者,助你洞悉技术趋势、了解创新AI产品应用。 新鲜AI产品点击了解:AIbase - 智能匹配最适合您的AI产品和网站 1、干翻AI …...

cmake进阶:目标属性

一. 简介 前面学习了 cmake 的一些目录属性,本文来学习 cmake的一些 目标属性。 目标属性,顾名思义就是目标对应的属性。 二. cmake进阶:目标属性 目标属性,顾名思义就是目标对应的属性。 cmake的所有目标属性可以通过如下网址…...

uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之使用jar包插件

前言 如果你不会编写安卓插件,你可以先看看我之前零基础的文章(uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之零基础编写安卓插件), 我们使用第三方包,jar包编写安卓插件 开始 把依赖包,放到某个模块的/libs目录(myTestPlug/libs) 还要到build…...

恢复数据,电脑数据恢复详细操作指南(4个方法)

“我经常会把很多重要的文件都保存在电脑上,但今天在清理电脑时好像误删了一些数据,有没有比较好用的数据恢复方法可以分享一下呢?请大家给我推荐几个吧!” 随着电脑的普及,我们越来越多地将重要数据存储在电脑中。然而…...

make SGX_MODE=SW

make SGX_MODESW...

【毕业设计】基于微信小程序的校园快递平台系统设计与实现

1.项目介绍 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统校园快递平台系统信息管理难度大,容错率…...

SWAT模型【建模方法、实例应用、高级进阶技能】实践

第一部分:SWAT模型实践部分 一、SWAT模型及应用介绍 1.1 面源污染概要 1.2 SWAT模型及应用 1.3 SWAT模型原理 1.4 SWAT模型输入文件 1.5 ArcGIS与SWAT关系 二、SWAT模型中GIS必备技术 2.1 GIS软件平台 2.2 ArcGIS10.6安装和注意事项 2.3 ArcGIS入门 2.…...

远动通讯屏功能和作用

远动通讯屏功能和作用 首先大家要先了解,什么叫远动通讯?远动通讯是电力系统指用于远程通信和远程控制的设备。它主要采集电发场站的电气运行参数与远程调度监控中心进行数据交互,并接收调度中心远程的指令控制。提高电力系统的运行效率和可靠…...

Dashboard 安装部署

Dashboard 安装部署 Dashboard 安装部署 一:下载 二:部署步骤 1.镜像下载及导入 国内直接拉外网镜像会失败,可在境外下载镜像 查看 deployment 里的镜像版本 Dashboard Deploymentcontainers:- name: kubernetes-dashboardimage: k8s.g…...

idea Maven 插件 项目多环境打包配置

背景 不同环境的配置文件不一样,打包方式也有差异 1. 准备配置文件 这里 local 为本地开发环境 可改为 dev 名称自定义 test 为测试环境 prod 为生产环境 根据项目业务自行定义 application.yml 配置: spring:profiles:#对应pom中的配置active: spring.…...

密室逃脱游戏-第12届蓝桥杯省赛Python真题精选

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第58讲。 密室逃脱游戏&…...

ES6-自学01

调用方法读取文件:如果失败就throw抛出err,成功则抛出data 2.使用promise封装,如果失败就改变状态为 reject(err) 如果成功就 resolve(返回成功的值) ,然后then,就可以获取返回的值,值toString()方法来把…...

PyQt5批量生成Checkbox及批量检查Checkbox的勾选状态

批量生成Checkbox并添加到TableWidget中 for i in range(10):checkbox_i QCheckBox(fCheckbox_{i}) # 生成Checkbox并命名为Checkbox_iself.ui_1.tableWidget_1.setCellWidget(i,1,checkbox_i) 批量检查勾选状态 # 批量生成Checkbox并存入列表 list_Checkbox_1 [] for …...

如何获得一个Oracle 23ai数据库(Virtual Appliance)

准确的说,是Oracle 23ai Free Developer版,因为企业版目前只在云上(OCI和Azure)和ECC上提供。 方法包括3种,本文介绍第1种: Virtual ApplianceRPM安装Docker 从此处下载虚拟机。 可以看到虚拟机需要4G内…...

跟TED演讲学英文:What moral decisions should driverless cars make by Iyad Rahwan

What moral decisions should driverless cars make? Link: https://www.ted.com/talks/iyad_rahwan_what_moral_decisions_should_driverless_cars_make Speaker: Iyad Rahwan Date: September 2016 文章目录 What moral decisions should driverless cars make?Introduct…...

【ITK配准】第七期 尺度(Metric)-规格化交互信息Metric

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享ITK中的互信息Metric,即itk::ITK中的互信息Metric,即itk::MutualInformationImageToImageMetric ,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享…...

Python练习 20240508一次小测验

Python基础 10道基础练习题 1. 个人所得税计算器描述‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬输入输出示例‪‬…...

桥梁施工污水需要哪些工艺设备

桥梁施工过程中产生的污水通常包含泥浆、油污、化学品残留等污染物。为了有效处理这些污水,确保施工现场的环境保护和合规性,通常需要以下工艺设备: 沉砂池:用于去除污水中的砂粒和其他重质无机物,减少对后续处理设备的…...

ADOP带你了解:长距离 PoE 交换机

您是否知道当今的企业需要的网络连接超出了传统交换机所能容纳的长度?这就是我们在长距离 PoE 交换机方面的专业化变得重要的地方。我们了解扩展网络覆盖范围的挑战,无论是在广阔的园区还是在多栋建筑之间。使用这些可靠的交换机,我们不仅可以…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...