Python 设计模式之单例模式

所谓单例模式,就是指一个实例对象只产生一次
创建唯一的一个实例对象。

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了

【单例模式优缺点】
【优点】
一、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
二、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
【缺点】
一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期

不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用

单例模式的简单理解:

1 单例模式 只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。
2 单例的缺点 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
用单例模式,就是在适用其优点的状态下使用 。

"""

单例模式特别像中国的婚姻法:
一夫一妻制
如果需要结婚,必须到民政局登记
民政局 检测两个人的户口本 看上面的结婚状态
已婚 不予登记
未婚  给予登记

那么按照这个思路实现python中的单例模式
1.需要一个方法,可以去控制当前对象的创建过程
__new__

2.需要一个标识来存储和表示是否有对象
创建一个私有属性进行存储,默认值为None

3.在创建对象的方法中去检测和判断是否有对象?
如果没有对象,则创建对象,并把对象存储起来,返回对象
如果存储的是对象,则直接返回对象,就不需要创建新的对象了
"""

# class Danli():
#     obj = 1
#     def __new__(cls, *args, **kwargs):
#         print(*args)
#         return cls
#
#
# d = Danli()
# print(d)#<class '__main__.Danli'>


class Danli():
    #2.定义私有属性,存储对象,默认值为None
    __obj = None

    #1.定义构造方法
    def __new__(cls, *args, **kwargs):
        #3.在创建对象的过程中,判断是否有对象
        if not cls.__obj:
            #判断如果没有对象,则创建对象,并且存储起来
            cls.__obj = object.__new__(cls)
        #直接把存储的对象返回
        return cls.__obj

#实例化对象,返回的是同一个内存地址
d1 = Danli()
print(d1)#<__main__.Danli object at 0x000001FA3E4528D0>

d2 = Danli()
print(d2)#<__main__.Danli object at 0x000001D970591940>

d3 = Danli()
print(d3)#<__main__.Danli object at 0x000001D970591940>

案例:

from typing import Any


class Car:
    #声明实例对象未创建为None
    instance = None #类属性
    #控制实例变量的属性,默认是未被赋予属性
    isCreate = False

    def __new__(cls,brand,color,wheel):
        if Car.instance == None:
            #创建实例对象
            Car.instance = super().__new__(cls)
        return Car.instance

        # #返回的是创建实例对象的内存地址
        # x = super().__new__(cls)
        # print(x)
        # return x

    def __init__(self,brand,color,wheel):
        if Car.isCreate == False:
            self.brand = brand
            self.color = color
            self.wheel = wheel
            Car.isCreate = True

    def show(self):
        print(self.brand,self.color,self.wheel)

#创建类的实例对象
c1 = Car("五菱宏光","粉色",4)
print(id(c1))
c1.show()
c2 = Car("拖拉机","黄金色",4)
c2.show()
print(id(c2))

c3 = Car("路虎","白色",4)
print(id(c3))
c3.show()
输出结果:
2033404387168
五菱宏光 粉色 4
五菱宏光 粉色 4
2033404387168
2033404387168
五菱宏光 粉色 4
# class D:
# #     #在类里 快捷键 Ctrl+o 快速生成(Select Methods to override)选择重写或实现方法
# #     def __new__(cls) -> Any:
# #         return super().__new__(cls)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值