用Python实现单例模式

这篇具有很好参考价值的文章主要介绍了用Python实现单例模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是单例模式

单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

单例模式的应用场景

单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:

1.需要频繁实例化然后销毁的对象。

2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

3.有状态的工具类对象。

4.频繁访问数据库或文件的对象。

以下都是单例模式的经典使用场景:

1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

2.控制资源的情况下,方便资源之间的互相通信。如线程池等。

单例模式的优缺点

优点:

1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例

2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。

3.提供了对唯一实例的受控访问。

4.由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。

5.允许可变数目的实例。

6.避免对共享资源的多重占用。

缺点:

1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。

2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。

3.单例类的职责过重,在一定程度上违背了“单一职责原则”。

4.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。

实现单例模式的几个实例

使用类变量实现单例模式

在 Python 中,可以通过定义一个类变量来实现单例模式,这个类变量可以存储单例实例的引用,如果该变量已经存储了一个实例,就直接返回该实例的引用,否则就创建一个新实例并将其存储在类变量中。

class Singleton:
    __instance = None   # 用于存储单例实例的类变量

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance

s1 = Singleton()
s2 = Singleton()
print(s1 == s2)   # True,因为 s1 和 s2 引用的是同一个实例

在这个例子中,我们定义了一个名为 `Singleton` 的类,它有一个类变量 `__instance`,用于存储单例实例的引用。在类的构造方法 `__new__` 中,我们首先检查 `__instance` 是否为 None,如果是,则说明还没有创建实例,于是调用父类的 `__new__` 方法创建一个新实例并将其赋值给 `__instance`,然后返回该实例的引用。如果 `__instance` 不为 None,则说明已经存在一个实例,于是直接返回该实例的引用。

最后,我们创建了两个 `Singleton` 类的实例 `s1` 和 `s2`,并将它们分别赋值给变量 `s1` 和 `s2`。由于单例模式的特性,我们期望 `s1` 和 `s2` 引用的是同一个实例,因此打印 `s1 == s2` 的结果应该为 True。除了使用类变量存储单例实例的引用之外,还可以使用装饰器或元类来实现单例模式。

使用装饰器实现单例模式

def singleton(cls):
    instances = {}
    def getinstance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    pass

a = MyClass()
b = MyClass()
print(a == b)   # True,因为 a 和 b 引用的是同一个实例

在这个例子中,我们定义了一个名为 `singleton` 的装饰器,它会接受一个类作为参数,返回一个新的函数 `getinstance`。在 `getinstance` 函数中,我们首先检查 `cls` 是否在 `instances` 字典中,如果不在,则说明还没有创建实例,于是调用 `cls` 的构造方法创建一个新实例并将其存储在 `instances` 中,然后返回该实例的引用。如果 `cls` 已经在 `instances` 中,则直接返回该实例的引用。最后,我们用 `@singleton` 装饰器修饰了一个名为 `MyClass` 的类,使其成为单例类。

使用元类实现单例模式

class Singleton(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 MyClass(metaclass=Singleton):
    pass

a = MyClass()
b = MyClass()
print(a == b)   # True,因为 a 和 b 引用的是同一个实例

在这个例子中,我们定义了一个名为 `Singleton` 的元类,它会在每次创建类时被调用。在 `Singleton` 的 `__call__` 方法中,我们首先检查 `cls` 是否在 `_instances` 字典中,如果不在,则说明还没有创建实例,于是调用父类的 `__call__` 方法创建一个新实例并将其存储在 `_instances` 中,然后返回该实例的引用。如果 `cls` 已经在 `_instances` 中,则直接返回该实例的引用。最后,我们用 `metaclass=Singleton` 指定了一个元类,使其成为 `MyClass` 的元类,从而使 `MyClass` 成为单例类。除了上述的几种实现方式外,还有其他的一些实现单例模式的方法。

使用模块实现单例模式

在 Python 中,模块在导入时只会被执行一次,因此可以使用模块来实现单例模式。例如,我们可以创建一个名为 `mysingleton.py` 的模块,并在其中定义一个单例类:

class MySingleton:
    def __init__(self):
        self.name = "Singleton"

my_singleton = MySingleton()

在另一个文件中,我们可以导入 `mysingleton` 模块,并使用其中的单例对象 `my_singleton`:

from mysingleton import my_singleton
print(my_singleton.name)   # "Singleton"

在这个例子中,我们在 `mysingleton.py` 模块中定义了一个名为 `MySingleton` 的单例类,并在该类的构造方法中定义了一个名为 `name` 的实例变量。在该模块中,我们还创建了一个名为 `my_singleton` 的 `MySingleton` 类的实例,并将其赋值给一个全局变量。在另一个文件中,我们通过 `from mysingleton import my_singleton` 导入了 `my_singleton` 对象,并打印了它的 `name` 变量。

使用闭包实现单例模式

在 Python 中,闭包是一种可以捕获其定义域中的变量并将其封装在函数对象中的方法。可以使用闭包来实现单例模式。例如,我们可以创建一个函数 `singleton`,它会返回一个内部函数 `get_instance`,该函数用于创建并返回单例对象:

def singleton(cls):
    instance = None
    def get_instance(*args, **kwargs):
        nonlocal instance
        if instance is None:
            instance = cls(*args, **kwargs)
        return instance
    return get_instance

@singleton
class MyClass:
    pass

a = MyClass()
b = MyClass()
print(a == b)   # True,因为 a 和 b 引用的是同一个实例

在这个例子中,我们定义了一个名为 `singleton` 的函数,它接受一个类作为参数,并返回一个内部函数 `get_instance`。在 `get_instance` 函数中,我们首先声明一个名为 `instance` 的变量,并将其初始化为 None。然后,我们检查 `instance` 是否为 None,如果是,则说明还没有创建实例,于是调用 `cls` 的构造方法创建一个新实例并将其赋值给 `instance`,然后返回该实例的引用。如果 `instance` 不为 None,则说明已经存在一个实例,直接返回该实例的引用。最后,我们用 `@singleton` 装饰器修饰了一个名为 `MyClass` 的类,使其成为单例类。

使用单例模式的注意事项

在使用单例模式时,需要注意以下几点:

  1. 确保单例类的唯一性:单例类应该只有一个实例,并且该实例应该在整个程序中都可用。因此外,还需要注意以下几点:

  1. 线程安全:如果多个线程同时调用单例类的构造方法,可能会创建多个实例。因此,需要采取线程安全的措施,如使用锁或原子操作。

  1. 生命周期管理:由于单例对象在整个程序中都可用,因此需要考虑它的生命周期。单例对象可能需要在程序退出时进行清理操作,例如关闭数据库连接或保存缓存数据。

  1. 依赖管理:如果单例对象依赖于其他对象,则需要确保这些依赖对象也是单例对象。否则,可能会出现多个实例之间的状态不一致的问题。

总之,单例模式是一种非常有用的设计模式,它可以确保一个类只有一个实例,并且该实例在整个程序中都可用。在 Python 中,可以使用多种方式实现单例模式,如使用类装饰器、元类、模块、闭包等。在实现单例模式时,需要考虑线程安全、生命周期管理和依赖管理等问题,以确保单例对象的正确性和可靠性。文章来源地址https://www.toymoban.com/news/detail-400584.html

到了这里,关于用Python实现单例模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python实现单例模式及其应用

    单例模式是一种常见的设计模式,它保证一个类只能被实例化一次,并提供了一个全局访问点来获取这个唯一的实例。 在 Python 中,可以通过使用装饰器、元类或模块等方式实现单例模式。下面分别介绍这三种方法: 1.使用装饰器实现单例模式 解析: 上述代码中,我们定义

    2024年02月07日
    浏览(31)
  • Python 实现单例模式的五种写法!

    单例模式(Singleton Pattern) 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。 比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类

    2024年02月10日
    浏览(34)
  • Python 实现单例模式的几种方式以及存在的问题

    Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。 直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象 先执行了类的__new__方法(我们没写时,默认调用ob

    2024年01月22日
    浏览(34)
  • 【单例设计模式原理详解】Java/JS/Go/Python/TS不同语言实现

    单例模式(Singleton Pattern)属于创建型设计模式,这种模式只创建一个单一的类,保证一个类只有一个实例,并提供一个访问该实例的全局节点。 当您想控制实例数目,节省系统资源,并不想混用的时候,可以使用单例模式。单例有很多种实现方式,主要分为懒汉和饿汉模式

    2023年04月27日
    浏览(70)
  • 什么是单例模式

    所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 单例模式有两种方式:1) 饿汉式 2) 懒汉式 演示 饿汉式 和 懒汉式 单例模式的实现。 步骤如下: 构造器私有化 =》 防止其

    2024年02月12日
    浏览(34)
  • 什么是单例模式,如何在Java中实现单例?

    单例模式是一种创建对象的设计模式,它确保只有一个实例,并提供对该实例的全局访问点。在Java中实现单例有懒汉式和饿汉式两种方式。 懒汉式单例模式: 在懒汉式单例模式中,对象创建在第一次使用时才会被创建。例如,当某个类第一次被实例化时,JVM会在堆内存中分

    2024年02月15日
    浏览(43)
  • 单例模式类设计|什么是饿汉模式和懒汉模式

    那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量干货博客汇总 https://blog.csdn.net/yu_cblog/category_12379430.html?spm=1001.2014.3001.5482 一个类只能创建一个对象,

    2024年02月16日
    浏览(33)
  • 单例模式的优点和缺点分别是什么?

    单例模式和枚举饿汉式单例模式都是设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。它们的区别在于实例的创建时间和线程安全性。 单例模式要求一个类只有一个实例,并提供一个全局访问点。常见的实现方式包括懒汉式、饿汉式、双重校验锁和枚举等。

    2024年02月20日
    浏览(26)
  • 【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式

    🍎 个人博客: 个人主页 🏆 个人专栏: JAVA ⛳️   功不唐捐,玉汝于成 目录 前言 正文 懒汉式(Lazy Initialization): 双重检查锁定(Double-Checked Locking): 结语 我的其他博客 在软件设计中,单例设计模式是一种重要的设计思想,它确保了一个类只有一个实例,并提供了一

    2024年01月15日
    浏览(41)
  • DCL 单例模式设计为什么需要 volatile 修饰实例对象

     DCL 问题,是在基于双重检查锁设计下的单例模式中,存在不 完整对象的问题。而这个不完整对象的本质,是因为指令重排序导致的。 当我们使用 instance=new DCLExample()构建一个实例对象的时候,因为 new 这个操作并不是原子的。所以这段代码最终会被编译成 3 条指令: 为对象

    2024年02月08日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包