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

一、说明

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

(一) 解决问题

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

(二) 使用场景

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

二、结构

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

三、伪代码

python 复制代码
#!/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))

四、优缺点

优点

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

缺点

  • 难以测试和调试:由于单例对象是全局唯一的,其行为可能与其他对象存在耦合,导致测试和调试困难。
  • 难以扩展:单例对象通常只有一个实例,如果需要扩展功能或增加复杂性,可能会面临较大的挑战。
  • 线程安全问题:在多线程环境下,如果没有正确地实现线程同步,可能会导致单例对象的实例化出现问题或产生竞态条件。
  • 过度使用可能会产生依赖和耦合:如果过度使用单例模式,可能会导致代码之间的耦合度过高,不利于代码的维护和重构。
相关推荐
Dxy12393102162 小时前
Python PDFplumber详解:从入门到精通的PDF处理指南
开发语言·python·pdf
在努力的韩小豪4 小时前
如何从0开始构建自己的第一个AI应用?(Prompt工程、Agent自定义、Tuning)
人工智能·python·llm·prompt·agent·ai应用·mcp
Otaku love travel5 小时前
实施运维文档
运维·windows·python
测试老哥6 小时前
软件测试之单元测试
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
presenttttt6 小时前
用Python和OpenCV从零搭建一个完整的双目视觉系统(六 最终篇)
开发语言·python·opencv·计算机视觉
测试19987 小时前
软件测试之压力测试总结
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·压力测试
李昊哲小课8 小时前
销售数据可视化分析项目
python·信息可视化·数据分析·matplotlib·数据可视化·seaborn
烛阴8 小时前
带参数的Python装饰器原来这么简单,5分钟彻底掌握!
前端·python
全干engineer8 小时前
Flask 入门教程:用 Python 快速搭建你的第一个 Web 应用
后端·python·flask·web
nightunderblackcat9 小时前
新手向:Python网络编程,搭建简易HTTP服务器
网络·python·http