Python设计模式详解之1 —— 单例模式

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供全局访问点。单例模式适用于需要确保全局唯一实例的场景,例如配置管理、日志记录器、数据库连接等。

1. 单例模式的特点

  • 全局唯一性:在整个应用程序的生命周期内,单例类只能有一个实例。
  • 全局访问:提供了一个全局访问点,任何地方都可以获取到该实例。
  • 延迟实例化:单例模式可以延迟实例化,即实例在第一次使用时才创建。

2. 实现单例模式的方法

在Python中,可以通过多种方式实现单例模式。以下是几种常见的方法:

方法一:使用类的静态实例
class Singleton:
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

# 测试
obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)  # 输出: True

解释:

  • 类变量 _instance 用于保存类的唯一实例。
  • __new__ 方法在实例创建时调用,确保实例只会被创建一次。
方法二:使用装饰器
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 MyClass:
    pass

# 测试
obj1 = MyClass()
obj2 = MyClass()
print(obj1 is obj2)  # 输出: True

解释:

  • 装饰器 singleton 用字典存储类的实例,如果实例不存在,就创建一个新的实例。
方法三:使用模块

Python模块本身就是单例的。可以直接在模块中定义全局变量来实现单例模式:

# singleton_module.py
class Singleton:
    def __init__(self):
        self.value = 42

singleton_instance = Singleton()

解释:

  • 模块在首次导入时会被初始化并保持单例状态。

使用元类(metaclass)来实现单例模式是Python中特有且更高级的方式。元类是控制类创建行为的“类的类”,通过自定义元类,我们可以控制类的实例化过程来实现单例模式。

方法四:使用元类实现单例模式

使用元类实现单例模式的核心思想是在__call__方法中拦截类的实例化过程,从而确保类只有一个实例。

实现方法
class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            # 创建一个新的实例,并将其存入_instances字典中
            cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

# 使用元类实现单例模式的类
class SingletonClass(metaclass=SingletonMeta):
    def __init__(self):
        print("Instance created")

# 测试
obj1 = SingletonClass()
obj2 = SingletonClass()
print(obj1 is obj2)  # 输出: True

解释

  • SingletonMeta继承自type,因此是一个元类。
  • __call__方法在类实例化时被调用。通过重写此方法,我们可以控制类实例的创建过程。
  • _instances是一个类变量,用于保存每个类的唯一实例。如果类实例不存在,则调用super().__call__()来创建一个新实例并存储在_instances中;如果已存在,直接返回存储的实例。

元类实现的优点

  • 灵活性:可以将元类应用于多个不同的类,从而减少重复代码。
  • 可扩展性:方便地在单例逻辑中添加额外功能,如线程安全控制。

3. 线程安全性改进

在多线程环境中,需要确保单例模式是线程安全的。可以使用线程锁来实现:

import threading

class SingletonMeta(type):
    _instances = {}
    _lock = threading.Lock()  # 锁对象用于同步

    def __call__(cls, *args, **kwargs):
        with cls._lock:  # 确保线程安全
            if cls not in cls._instances:
                cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class SingletonClass(metaclass=SingletonMeta):
    def __init__(self):
        print("Instance created")

# 测试
obj1 = SingletonClass()
obj2 = SingletonClass()
print(obj1 is obj2)  # 输出: True

4. 应用场景

  • 日志系统:日志记录器在整个应用程序中应当只有一个实例来防止资源竞争。
  • 配置管理:使用单例模式来加载和管理配置文件以确保一致性。
  • 资源共享:在涉及共享资源如数据库连接池时,单例模式可以有效管理连接实例。

5. 注意事项

  • 单例模式的实现要保证线程安全,特别是在多线程应用中。
  • 过度使用单例模式会导致代码耦合度高,因此应谨慎使用,确保符合设计需求。

单例模式虽然简单,但其全局状态可能带来潜在的问题,例如难以进行单元测试或状态管理不清晰。在使用时要权衡利弊。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

视频流媒体播放器EasyPlayer.js无插件直播流媒体音视频播放器Android端webview全屏调用无效问题

流媒体播放器的核心技术与发展趋势正在不断推动着行业的变革。未来,随着技术的不断进步和应用场景的不断拓展,流媒体播放器将为用户带来更加便捷、高效、个性化的观看体验。同时,流媒体播放器也会成为数字娱乐产业的重要组成部分,…

【Python · PyTorch】卷积神经网络 CNN(LeNet-5网络)

【Python PyTorch】卷积神经网络 CNN(LeNet-5网络) 1. LeNet-5网络※ LeNet-5网络结构 2. 读取数据2.1 Torchvision读取数据2.2 MNIST & FashionMNIST 下载解包读取数据 2. Mnist※ 训练 LeNet5 预测分类 3. EMnist※ 训练 LeNet5 预测分类 4. Fash…

Live2D嵌入前端页面

废话不多说,直接看效果,给页面中嵌入的一个动态的二次元人物,美化页面,实际效果自行查看。 教程开始 一. 把项目拉取到本地 项目地址 自行下载到本地,下载方式自行选择。 二.把项目文件夹放到前端页面目录内 三.把下…

openlayer 将 GeoJSON 格式的 geometry 转换为 feature

openlayer 将 GeoJSON 格式的 geometry 转换为 feature geometry格式如图: 代码: /*** 将 GeoJSON 格式的 geometry 转换为 feature* param geometry* returns*/geoJsonToWkt(geometry) {const { coordinates, type } geometry;let olGeometry;swit…

web应用安全和信息泄露预防

文章目录 1:spring actuator导致的信息泄露1.1、Endpoint配置启用检测1.2、信息泄露复现1.3、防御 2:服务端口的合理使用3:弱口令(密码)管理4:服务端攻击4.1、短信业务,文件上传等资源型接口1、…

基于LSTM的新闻中文文本分类——基于textCNN与textRNN

构建词语字典 def build_vocab(file_path, tokenizer, max_size, min_freq):# 定义词汇表字典:使用 vocab_dic {} 初始化一个空字典,用于存储每个词及其出现频率vocab_dic {}with open(file_path, r, encodingUTF-8) as f:for line in tqdm(f):lin l…

MySQL 的 Change Buffer 是什么?它有什么作用?

MySQL 的 Change Buffer 是什么?它有什么作用? MySQL 是目前广泛使用的开源数据库管理系统,其中的 InnoDB 存储引擎凭借其高性能、高可靠性以及强大的事务支持,成为了默认的存储引擎。在 InnoDB 的众多优化机制中,Cha…

Spark 之 Aggregate

Aggregate 参考链接: https://github.com/PZXWHU/SparkSQL-Kernel-Profiling 完整的聚合查询的关键字包括 group by、 cube、 grouping sets 和 rollup 4 种 。 分组语句 group by 后面可以是一个或多个分组表达式( groupingExpressions )…

C#高级:Winform中的自定义窗体输入

目录 一、多样式输入(无封装) 1.代码 2.效果 二、单输入框封装 1.使用 2.封装 3.效果 三、组合框批量输入封装 1.使用 2.封装 3.效果 一、多样式输入(无封装) 1.代码 private async void button1_Click(object send…

使用GDB或Delve对已经运行起来的Go程序进行远程调试

同步发布在我的博客,欢迎来点赞。 使用 GDB 或 Delve 对已经运行起来的 Go 程序进行远程调试 使用 GDB 或 Delve 对已经运行起来的 Go 程序进行远程调试 背景 Java 程序可以很方便地通过 jdwp 参数指定一个对外端口进行远程调试,如 java \ -agentlib…

简单实现QT对象的[json]序列化与反序列化

简单实现QT对象的[json]序列化与反序列化 简介应用场景qt元对象系统思路实现使用方式题外话 简介 众所周知json作为一种轻量级的数据交换格式,在开发中被广泛应用。因此如何方便的将对象数据转为json格式和从json格式中加载数据到对象中就变得尤为重要。 在python类…

Java开发经验——开发常用工具类

摘要 本文介绍了Java开发中常用的工具类,包括Apache Commons Collections的SetUtils、Google Guava的Sets、Apache Commons Lang的ArrayUtils等,以及它们在集合操作、数组操作、字符串处理、JSON处理等方面的应用。文章还涉及了Optional类、Money工具类…

esp32c3开发板通过micropython的mqtt库连MQTT物联网消息服务器

MQTT介绍 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息协议,旨在设备之间进行通信,尤其是在网络条件较差的情况下。MQTT v3.1.1 和 MQTT v5 是该协议的两个主要版本。 MQTT v3.1.1: 优点&#xff…

【IDE】使用指南

定期更新实用技能,建议关注收藏点赞。 友情链接: 点击跳转常见代码编辑器的报错解决方案 目录 常用快捷键pycharm右下角边栏脚本头安装IDE的插件git配置TODO 代码编辑器里有许多小技巧,便于办公。本篇主要以pycharm,vscode等主流常用IDE为…

OpenGL入门009——漫反射在片段着色器中的应用

本节将在片段着色器中应用漫反射 文章目录 一些概念漫反射 实战简介dependenciesshadervsshader.fs utilsCube.cpp main.cppCMakeLists.txt最终效果 一些概念 漫反射 概述: 描述的是粗糙表面对光的反射,反射的光线相关各个方向均匀分布,与视…

删库跑路,启动!

起因:这是一个悲伤的故事,在抓logcat时 device待机自动回根目录了,而题主对当前路径的印象还停留在文件夹下,不小心在根目录执行了rm -rf * … 所以,这是个悲伤的故事,东西全没了…device也黑屏了&#xff…

Ubuntu下的Eigen库的安装及基本使用教程

一、Eigen库介绍 简介 Eigen [1]目前最新的版本是3.4,除了C标准库以外,不需要任何其他的依赖包。Eigen使用的CMake建立配置文件和单元测试,并自动安装。如果使用Eigen库,只需包特定模块的的头文件即可。 基本功能 Eigen适用范…

OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)

本文来源公众号“OpenCV与AI深度学习”,仅用于学术分享,侵权删,干货满满。 原文链接:分享|16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括: 1. 人…

MySQL win安装 和 pymysql使用示例

目录 一、MySQL安装 下载压缩包: 编写配置文件: 配置环境变量: 初始化服务和账户 关闭mysql开机自启(可选) 建议找一个数据库可视化软件 二、使用pymysql操作数据库 安装pymysql 示例代码 报错处理 一、My…

springboot基于微信小程序的停车场管理系统

摘 要 停车场管理系统是一种基于移动端的应用程序,旨在方便车主停车的事务办理。该小程序提供了便捷的停车和功能,使车主能够快速完成各项必要的手续和信息填写。旨在提供一种便捷、高效的预约停车方式,减少停车手续的时间和精力成本。通过该…