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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/6512.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【UnityRPG游戏制作】Unity_RPG项目_玩法相关

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:就业…

【算法与数据结构】哈希表

文章目录 引入哈希函数介绍便利店的例子Python3 中的哈希表C 中的哈希表 应用将散列表用于查找防止重复将散列表用作缓存 哈希冲突与解决链地址法开放寻址 总结参考资料写在最后 引入 假设你在一家便利店上班,你不熟悉每种商品的价格,在顾客需要买单是时…

详述DM9161芯片的特性和用法

目录 概述 1. 认识DM9161 2 DM9161的特性 2.1 特性总结 2.2 结构框图 3 功能描述 4 RMII接口 4.1 100Base-TX Operation 4.2 10Base-T Operation 4.3 Auto-Negotiation 4.4 HP Auto-MDIX功能描述 6 DM9161的寄存器 6.1 寄存器列表 6.2 寄存器功能介绍 6.2.1 基本…

ubuntu20中ros与anaconda的python版本冲突问题

系统环境 原本系统是ubuntu20 noetic,python都在/usr/bin中,一共是两个版本的python,一个是python3.8,另一个是python2.7。 问题发现 当安装anaconda后,并且将anaconda的bin目录加入到系统环境中时候,…

Stable Diffusion webUI 配置指南

Stable Diffusion webUI 配置指南 本博客主要介绍部署Stable Diffusion到本地,生成想要的风格图片。 文章目录 Stable Diffusion webUI 配置指南1、配置环境(1)pip环境[可选](2)conda环境[可选] 2、配置Stable Diffu…

Monorepo(单体仓库)与MultiRepo(多仓库): Monorepo 单体仓库开发策略与实践指南

🌟 引言 在软件开发的浩瀚宇宙里,选择合适的代码管理方式是构建高效开发环境的关键一步。今天,我们将深入探讨两大策略——Monorepo(单体仓库)与MultiRepo(多仓库),并通过使用现代化…

CMakeLists.txt语法规则:部分常用命令说明一

一. 简介 前一篇文章简单介绍了CMakeLists.txt 简单的语法。文章如下: CMakeLists.txt 简单的语法介绍-CSDN博客 接下来对 CMakeLists.txt语法规则进行具体的学习。本文具体学习 CMakeLists.txt语法规则中常用的命令。 二. CMakeLists.txt语法规则:…

【Qt问题】VS2019 Qt win32项目如何添加x64编译方式

解决办法: 注意改为x64版本以后,要记得在项目属性里,修改Qt Settings、对应的链接include、lib等 参考文章 VS2019 Qt win32项目如何添加x64编译方式_vs2019没有x64-CSDN博客 有用的知识又增加了~

Spring事件

📝个人主页:五敷有你 🔥系列专栏:Spring⛺️稳中求进,晒太阳 Spring事件 简洁 Spring Event(Application Event)就是一个观察者模式,一个bean处理完任务后希望通知其他Bean的…

OpenCV人脸识别C++代码实现Demo

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,它提供了很多函数,这些函数非常高效地实现了计算机视觉算法。 官网:https://opencv.org/ Github: https://github.com/opencv/opencv Gitcode…

查找算法与排序算法

查找算法 二分查找 (要求熟练) // C// 二分查找法(递归实现) int binarySearch(int *nums, int target, int left, int right) // left代表左边界,right代表右边界 {if (left > right) return -1; // 如果左边大于右边,那么…

初始化Linux或者Mac下Docker运行环境

文章目录 1 Mac下安装Docker2 Linux下安装Docker2.1 确定Linux版本2.2 安装Docker2.3 配置加速镜像 3 Docker安装校验4 安装docker-compose4.1 直接下载二进制文件4.2 移动二进制文件到系统路径4.3 设置可执行权限4.4 验证安装 1 Mac下安装Docker mac 安装 docker 还是比较方便…

配置Zephyr编译环境

安装chocolatey 以管理员身份运行PowerShell,然后在PowerShell下执行以下命令,安装chocolatey。 Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol [System.Net.ServicePointManager]::Securi…

【深度学习实战(32)】模型结构之解耦头(de-coupled head)与耦合头(coupled head)

一、传统耦合头局限性 传统的检测模型,如YOLOv3和YOLOv4,使用的是单一的检测头,它同时预测目标类别和框的位置。然而,这种设计存在一些问题。首先,将类别预测和位置预测合并在一个头中,可能导致一个任务的…

Wireshark CLI | 过滤包含特定字符串的流

问题背景 源自于和朋友的一次技术讨论,关于 Wireshark 如何查找特定字符串所在的 TCP 流,原始问题如下: 仔细琢磨了下,基于我对 Wireshark 的使用经验,感觉一步到位实现比较困难,所以想着说用 Wireshark C…

旅游系列之:庐山美景

旅游系列之:庐山美景 一、路线二、住宿二、庐山美景 一、路线 庐山北门乘坐大巴上山,住在上山的酒店东线大巴游览三叠泉,不需要乘坐缆车,步行上下三叠泉即可,线路很短 二、住宿 长江宾馆庐山分部 二、庐山美景

Photoshop中图像编辑的基本操作

Photoshop中图像编辑的基本操作 Photoshop中调整图像窗口大小Photoshop中辅助工具的使用网格的使用标尺的使用注释工具的使用 Photoshop中置入嵌入式对象Photoshop中图像与画布的调整画布大小的修改画布的旋转图像尺寸的修改 Photoshop中撤销与还原采用快捷键进行撤销与还原采用…

机器学习之基于Jupyter多种混合模型的糖尿病预测

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着现代生活方式的改变,糖尿病的患病率在全球范围内呈现上升趋势。糖尿病是一种慢性代谢…

上位机图像处理和嵌入式模块部署(树莓派4b使用lua)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 lua是一个脚本语言,比c语言开发容易,也没有python那么重,整体使用还是非常方便的。一般当成胶水语言进行开发&a…

【Hadoop】--基于hadoop和hive实现聊天数据统计分析,构建聊天数据分析报表[17]

目录 一、需求分析 1、背景介绍 2、目标 3、需求 4、数据内容 5、建库建表 二、ETL数据清洗 1、数据问题 2、需求 3、实现 4、扩展概念:ETL 三、指标计算 1、指标1:统计今日消息总量 2、指标2:统计每小时消息量、发送量和接收用…