【Python笔记-设计模式】单例模式

一、说明

单例是一种创建型设计模式,能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。

(一) 解决问题

维护共享资源(数据库或文件)的访问权限,避免多个实例覆盖同一变量,引发程序崩溃。

(二) 使用场景

  • 数据库连接
  • 文件操作
  • 所有需要维护对象变量一致性的场景

二、结构

  1. 单例 (Singleton) 类声明了一个名为get­Instance获取实例的静态方法来返回其所属类的一个相同实例。单例的构造函数必须对客户端 (Client) 代码隐藏。 调用获取实例方法必须是获取单例对象的唯一方式。

三、伪代码

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__doc__ = """
单例模式
"""

import threading


class Singleton1:
    """
    方法1, 实现__new__方法
    并在将一个类的实例绑定到类变量_instance上,
    如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回
    如果cls._instance不为None,直接返回cls._instance
    """
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        with cls._lock:
            if not cls._instance:
                cls._instance = super().__new__(cls)
        return cls._instance


class Singleton2(type):
    """
    方法2,实现metaclass,利用metaclass在实例化时已经创建好实例,
    从而实现单例模式,注意必须通过metaclass实现
    """
    _instances = {}
    _lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        with cls._lock:
            if cls not in cls._instances:
                cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]


def singleton(cls):
    """
    方法3,使用装饰器
    """
    _instance = None
    _lock = threading.Lock()

    def wrapper(*args, **kwargs):
        nonlocal _instance
        with _lock:
            if _instance is None:
                _instance = cls(*args, **kwargs)
        return _instance

    return wrapper


class MyClass:
    a = 1


class MyClass1(Singleton1):
    a = 1


class MyClass2(metaclass=Singleton2):
    a = 1


@singleton
class MyClass3:
    a = 1


if __name__ == '__main__':
    """
    非单例模式
    2 4787260528
    1 4787260480
    
    方法1, 实现__new__方法
    2 4787260336
    2 4787260336
    
    方法2, 实现metaclass
    3 4787260192
    3 4787260192
    
    方法3, 使用装饰器
    4 4787260144
    4 4787260144
    """
    print("非单例模式")
    s1 = MyClass()
    s2 = MyClass()
    s1.a = 2
    print(s1.a, id(s1))
    print(s2.a, id(s2))
    print()

    print("方法1, __new__方法实现")
    s1_1 = MyClass1()
    s1_2 = MyClass1()
    s1_1.a = 2
    print(s1_1.a, id(s1_1))
    print(s1_2.a, id(s1_2))
    print()

    print("方法2, metaclass实现")
    s2_1 = MyClass2()
    s2_2 = MyClass2()
    s2_1.a = 3
    print(s2_1.a, id(s2_1))
    print(s2_2.a, id(s2_2))
    print()

    print("方法3, 使用装饰器")
    s3_1 = MyClass3()
    s3_2 = MyClass3()
    s3_1.a = 4
    print(s3_1.a, id(s3_1))
    print(s3_2.a, id(s3_2))

四、优缺点

优点

  • 实例唯一:单例模式确保某个类只有一个实例,这有助于节省内存,因为只有一个对象实例在内存中。
  • 避免频繁创建和销毁对象:由于单例对象只创建一次,可以减少频繁的创建和销毁对象带来的性能开销。
  • 便于资源管理:单例模式可以确保某个资源或服务在整个应用程序中只有一个实例,方便对资源的统一管理和优化。
  • 提高性能和资源利用率:单例模式可以避免对资源的重复占用,从而提高性能和资源利用率。

缺点

  • 难以测试和调试:由于单例对象是全局唯一的,其行为可能与其他对象存在耦合,导致测试和调试困难。
  • 难以扩展:单例对象通常只有一个实例,如果需要扩展功能或增加复杂性,可能会面临较大的挑战。
  • 线程安全问题:在多线程环境下,如果没有正确地实现线程同步,可能会导致单例对象的实例化出现问题或产生竞态条件。
  • 过度使用可能会产生依赖和耦合:如果过度使用单例模式,可能会导致代码之间的耦合度过高,不利于代码的维护和重构。

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

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

相关文章

部署PXE高效批量网络装机

部署PXE高效批量网络装机 因在Cisco3850核心交换机中已开启DHCP 服务,因此不需要在配置DHCP服务。如果您的网络环境中也已有DHCP服务,也不用再配置DHCP服务了,直接部署PXE相关服务即可。 找一台linux系统的服务器,这本次试验用的是…

什么是零知识证明?

Web3 的核心原则之一——透明度,也可能是其最大的缺点之一。没有人希望他们的所有在线活动(从金融交易到个人身份数据)都可供任何人公开查看。为了使区块链能够扩展并变得更容易访问,隐私必须成为首要任务。 零知识证明能够改变我…

Codeforces Round 894 (Div. 3)

Gift Carpet(Problem - A - Codeforces) 题目大意:有一块儿地毯,上面有n行m列的字符,如果从左往右一列一列的读,可以读到“vika”,那么就输出yes,否则输出no。 思路:这…

【RuoYi-Vue-Plus学习】项目初始化时将sql导入数据库出现Finished with error解决方法之一

将sql导入数据库出现Finished with error,文末是最终解决方法。 问题描述:sql导入出现Finished with error 解决方法探索过程: 1)参考链接2和3,在mysql的bin目录下输入以下指令连接数据库 mysql -h localhost -u ro…

第25讲:顺序表专题

1.什么是数据结构 2.顺序表概念及结构 3.顺序表分类 4.实现动态顺序表 1.什么是数据结构 数据结构是计算机存储、组织数据的方式。可以用来完成通讯录项目。 2.顺序表概念及结构 2.1线性表 线性表是n个具有相同特性的数据元素的有限序列 常见的线性表:顺序表…

智能监控系统EasyCVR设备录像无法下载是什么原因?该如何解决?

视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,在视频监控播放上,TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放,可同时播放多路视频流&#…

【React教程】(2) React之JSX入门与列表渲染、条件渲染详细代码示例

目录 JSX环境配置基本语法规则在 JSX 中嵌入 JavaScript 表达式在 JavaScript 表达式中嵌入 JSXJSX 中的节点属性声明子节点JSX 自动阻止注入攻击在 JSX 中使用注释JSX 原理列表循环DOM Elements 列表渲染语法高亮 条件渲染示例1:示例2:示例3&#xff08…

递归方法的理解,什么时候递,什么时候归

简单总结一下递归。递归就是在运行的过程中调用自己。递归需要有一个出口,如果无限递归是没有意义的,而且递归到一定程度,程序就会由于栈内存溢出导致程序报错。 我们先来看段代码:建议大家先思考这个代码在控制台输出的结果是什…

性能测试+Jmeter介绍

文章目录 什么是性能测试?性能测试的目的性能测试分类一般性能测试负载测试压力测试大数据量测试配置测试稳定性测试 性能测试术语虚拟用户并发及并发用户数响应时间每秒事务数吞吐量、吞吐率点击率性能计数器资源利用率 性能测试流程测试计划阶段测试设计阶段测试开发阶段测试…

SQL中实现行列转换

目录 方法一:sum case when 方法二:sum if 方法三:pivot 现在有一张表class_gender,内容如下: classgender一年级女一年级女一年级男一年级男二年级女二年级女二年级男 现在我们要根据上表,统计得到下…

Redis常用数据结构与应用场景

常用数据结构 StringHashListSetZset String常用操作 String应用场景 Hash常用操作 hash应用场景 Hash结构优缺点 优点 同类数据归类整合存储,方便数据管理相比String操作消耗内存与spu更小相比string更节省空间 缺点 过期功能不能使用在field上,只用用在key上Redis集群…

java学习之路(2)-编译java文件运行Java文件

创建.java后缀文本文件HelloWorld .java 写入代码: public class HelloWorld { public static void main(String []args) { System.out.println("Hello World"); } } 运行cmd命令 找到代码所在目录 输入javac编译Java文件生成HelloWorld.class 编译:…

CentOS 7 部署 ZeroTier Moon 节点

ZeroTier是一套使用UDP协议构建的SD-WAN网络软件,其主要有三部分组成:行星服务器Planet、月亮服务器Moon、客户端节点LEFA,行星服务器是ZeroTier的根节点,可以采用ZeroTier官方的服务器,也可以使用开源代码自行搭建 月…

Android中下载 HAXM 报错 Intel® HAXM installation failed,如何解决?

最近在搭建 Flutter 环境,但是在 Android Studio 中安装 Virtual Device 时,出现了一个 问题 Intel HAXM installation failed. To install Intel HAXM follow the instructions found at: https://github.com/intel/haxm/wiki/Installation-Instructio…

深度强化学习(王树森)笔记09

深度强化学习(DRL) 本文是学习笔记,如有侵权,请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接:https://github.com/wangshusen/DRL 源代码链接:https://github.c…

【Servlet】Smart Tomcat插件简化Servlet开发流程及解决常见问题

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Servlet】 本专栏旨在分享学习Servlet的一点学习心得,欢迎大家在评论区交流讨论💌 目录 一、Smart Tomcat插件二…

【2023地理设计组一等奖】基于GIS的桥梁隧道三维建模与可视化

作品介绍 1 设计背景和意义 随着我国基础建设规模不断扩大和深入,构建桥梁可视化管理模型,全面推动智慧桥梁,已成为现代隧道桥梁建设行业的发展趋势。传统的桥梁建模工作需要复杂的算法设计并需要熟练编程实践技能,实现周期长。开发自主知识版权的桥梁建模软件系统或专用插…

时间复杂度解释

时空复杂度概述 首先o(1), o(n), o(logn), o(nlogn)是用来表示对应算法的时间复杂度,这是算法的时间复杂度的表示。不仅仅用于表示时间复杂度,也用于表示空间复杂度。 算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行这个算法所需要…

Keepalived + DR 集群

目录 1、Keepalive VRRP 说明 故障切换 工作原理 核心组件 2、Keepalived DR 集群 拓扑规划 前期准备 配置 Httpd 服务 配置 Nginx 服务 配置 LVS 主 node_01 配置 LVS 从 node_02 测试 LVS 集群 测试主备切换 3、Keepalived 脑裂现象 4、Keepalived 心态检测 …

C++字符串的常用操作函数全总结

文章目录 1.string、string.h和cstring的区别2.字符串定义3.求字符串的长度(也可以求array对象长度)4.输入字符串5.分割截取字符串4.在字符串中查找指定子字符串,并返回其第一次出现的位置5.替换字符串中的一部分6.在字符串指定位置插入字符串7.复制字符…