首页 > 其他分享 >10月18日单例模式

10月18日单例模式

时间:2023-10-18 11:25:33浏览次数:34  
标签:10 18 self instance 实例 单例 def cls

目录

单例模式值类的绑定方法,装饰器方式

设计模式:

总共有23中设计模式,单例模式就是其中一个

单例模式:整个过程中只有一个实例,所有生成的实例都指向同一块内存空间

先举一个不是单例的代码

class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age



p1 = Person('fvv', 18)
p2 = Person('nick', 6666)
#输出内存地址
print(p1)
print(p2)

结果如图

从结果图可以看出这两个实例的内存地址是不一样的,不符合单例模式的要求

实现单例模式的第一种方式

第一种方式以类的绑定方法来实现

现在以下面的条件为例子来表达单例模式:

1.需求当用户端口和地址,实例化产生新对象
2.当用户不输入端口和地址,每次拿到的对象,都是同一个

略微复杂的代码能看懂就看,看不懂算,但是这个代码实现了

#需求当用户端口和地址,实例化产生新对象
#当用户不输入端口和地址,每次拿到的对象,都是同一个

class Sql():
    _instance = None#这里定义了一个参数一个变量
    def __init__(self, port, host):
        self.port = port
        self.host = host
    @classmethod
    def get_sigoleton(cls):
        import settings#这里引用我写的模块
        if cls._instance:
            return cls._instance

        else:
            cls._instance = cls(settings.PORT, settings.HOST)
        return cls._instance


s1=Sql.get_sigoleton()
s2=Sql.get_sigoleton()
print(s1)
print(s2)

来提供一个简化版

class Sql:
    # 类属性,用于存储单例实例
    _instance = None

    def __init__(self, port, host):#port是端口号,host是主机IP地址
        # 初始化数据库连接的端口和主机地址
        self.port = port
        self.host = host

    @classmethod
    def get_singleton(cls, port, host):
        # 类的绑定方法,用于获取单例实例
        if cls._instance is None:
            # 如果单例实例为None,表示还没有创建实例
            # 创建新的Sql实例,并赋值给类属性 _instance
            cls._instance = cls(port, host)
        # 返回已存在的单例实例
        return cls._instance

# 创建两个Sql实例,但实际上它们会是同一个实例
s1 = Sql.get_singleton(3360, '127.0.0.1')
s2 = Sql.get_singleton(3360, '127.0.0.1')

# 使用 is 运算符检查它们是否是同一个实例
# 由于它们都是通过 get_singleton 方法获取的,所以会返回 True
print(s1 is s2)#结果为True

这个代码省去了引用模块的那一步,同时也更简洁了

实现单例模式的第二种方式

通过装饰器来实现单例模式

复杂版

def get_sigoleton(cls):
    import settings#这里引用了
    _instance = cls(settings.PORT, settings.HOST)
    def wrapper(*args, **kwargs):

        if len(args)!=0 or len(kwargs)!=0:
            #表示传了参数,生成新对象
            res = cls(*args, **kwargs)
            return res
        else:
            return _instance
    return wrapper

@get_sigoleton#会把下面的Sql当参数传入,相当于:Sql = get_sigoleton(Sql)
class Sql():
    _instance = None
    def __init__(self, port, host):
        self.port = port
        self.host = host

s1 = Sql()
s2 = Sql()

print(s1)
print(s2)

现在以生活为例子来简单实现这个装饰器实现单例模式的方式

以洗衣机为例子

# 定义一个装饰器,用于创建单例对象
def zhuangshiqi(cls):
    instances = {}  # 用于存储单例对象的字典

    # 定义内部函数,用于创建或获取单例对象
    def get_instance(*args, **kwargs):
        # 如果类 cls 还没有创建单例对象,则创建并保存到 instances 字典中
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        # 如果已经存在单例对象,直接返回
        return instances[cls]

    return get_instance

# 使用装饰器创建单例类
@zhuangshiqi
class xiyiji:
    def __init__(self, brand):
        self.brand = brand

    def wash(self):
        print(f"{self.brand}洗衣机正在洗衣服")

# 家庭成员使用单例洗衣机
mom_washer = xiyiji("品牌X")
dad_washer = xiyiji("品牌X")

# 无论多少个家庭成员,都只有一个洗衣机
print(mom_washer is dad_washer)  # 输出 True,表示两者是同一个实例对象

实现单例模式的第三种方式

通过元类来实现单例

视频里的不利于理解这里提供简单的思路点:

#第三种,通过元类
class Coff:
    #使用类变量来存储唯一的咖啡店实例
    _instance = None

    def __new__(cls):
        #如果咖啡店实例不存在,创建并返回
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.coffee_count = 0
        return cls._instance


    def serve_coffee(self):
        self.coffee_count += 1
        print(f'制作了第{self.coffee_count}杯咖啡')

#客人来到唯一的咖啡店
man1 = Coff()
man2 = Coff()
print(man1 is man2)#因为都是同一个咖啡店实例这就符合了单例模式所以返回True
#点咖啡,表示这两个客人共享同一个咖啡店的实例
man1.serve_coffee()
man2.serve_coffee()
print(man1 is man2)#这里再进行判断结果还是True

结果如图

这里的咖啡店例子也说明了我单例模式的核心

假设有一个小镇上的唯一咖啡店。无论多少人想要一杯咖啡,他们都必须去这家咖啡店。咖啡店就像一个单例,只有一个实例。

在这个场景中,咖啡店就是单例,每个人都共享这个单例。这确保了在整个小镇上只有一家咖啡店,无论多少人来喝咖啡,他们都只能去这家店。

单例模式的核心概念是:只有一个实例对象,而不管有多少人尝试访问它。

第四种方法,通过模块导入(python的模块就是单例的体现)

首先生成一个模块settings这个模块

PORT = 3360
HOST = '127.0.0.1'
class Sql():
    def __init__(self, port, host):
        self.port = port
        self.host = host

s1 = Sql(PORT, HOST)

然后再调用这个模块

#第四种方法,通过模块导入(python的模块是天然的单例)

def test():
    from settings import s1#我导入settings生成好的实例
    print(s1)
def test2():
    from settings import s1
    print(s1)
#这些函数调用的都是同一个实例对象符合单例的想法
test()
test2()

结果如图

上面这么多代码说明了,单例实际作用有点类似多态性,无论有多少对象它们调用的都是同一个实例,就像点快餐的窗口就一个窗口,谁来点餐都是通过这个窗口(实例窗口对象)。

核心就有一句话:只有一个实例对象,而不管有多少人尝试访问它。

标签:10,18,self,instance,实例,单例,def,cls
From: https://www.cnblogs.com/slzjb/p/17771631.html

相关文章

  • CF1868C Travel Plan 题解
    原题翻译发现所有长度相同的简单路径的权值可能情况相同,且最长的简单路径长度为\(O(\logn)\)级别,考虑维护所有长度的简单路径在一棵树上出现的次数,每种简单路径的权值在所有树上出现的次数,相乘即使答案。我们考虑长度为\(x\)的路径对答案的贡献,考虑枚举这条路径的贡献\(......
  • P5018 [NOIP2018 普及组] 对称二叉树
    先递归判断当前子树是不是对称二叉树,如果是就取\(\max\)然后退出,否则继续递归左儿子的左子树和右儿子的右子树、左儿子的右子树和右儿子的左子树判断。最坏情况是每次都递归到叶子,也就是每层都是\(O(n)\)。但一共只有\(O(\logn)\)层,所以时间复杂度是\(O(n\logn)\)。......
  • 【2023-10-01】连岳摘抄
    23:59国家是大家的,爱国是每个人的本分。                                                 ——陶行知你很难接受的是:明明我仁至义尽,为什么她这么无情,这么残忍?人世间......
  • 【2023-10-02】连岳摘抄
    23:59兰生幽谷,不为莫服而不芳。舟在江海,不为莫乘而不浮。君子行义,不为莫知而止休。                                                 ——《淮南子》我给你两个学习......
  • 10.18算法
    3的幂给定一个整数,写一个函数来判断它是否是3 的幂次方。如果是,返回true;否则,返回false。整数n是3的幂次方需满足:存在整数x使得n==3x 示例1:输入:n=27输出:true示例2:输入:n=0输出:false示例3:输入:n=9输出:true示例4:输入:n=45输出:false 提示:-231<=n......
  • 分享10个非常好看的QQ空间特效代码
    以下是10种常见的QQ空间特效代码,这些代码可以在QQ空间中实现不同的视觉效果: 1.飘雪特效```javascript:void(newImage().src="http://img.t.sinajs.cn/t35/style/images/common/face/02.gif?v=3.848");```2.彩虹特效```javascript:void(newImage().src="http://img.t.sin......
  • go语言使用单例模式封装数据库连接池
    packagesingledbimport( "gorm.io/driver/mysql" "gorm.io/gorm" "sync")//数据库连接对象只有一个var( db*gorm.DB Oncesync.Once//只执行一次某个操作的机制)funcGetDbInstance()*gorm.DB{ Once.Do(func(){ varerrerror dsn:=&q......
  • 14.10 Socket 套接字选择通信
    对于网络通信中的服务端来说,显然不可能是一对一的,我们所希望的是服务端启用一份则可以选择性的与特定一个客户端通信,而当不需要与客户端通信时,则只需要将该套接字挂到链表中存储并等待后续操作,套接字服务端通过多线程实现存储套接字和选择通信,可以提高服务端的并发性能,使其能够同......
  • 20231017
    上午学了算法与数据结构中的线索二叉树睡了一整个下午帮助同学在关于开发的问题上躺床上看了编译器相关的书,挺有趣的。编译的几个阶段,语法分析,词法分析,抽象语法树,还有解释器生成器的使用什么的,熟悉但我也不怎么会用的正则表达式,好像编译器也并不是之前认知中的黑盒子了,现在就只......
  • 【专题】小红书母婴618品牌种草趋势报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=33866品牌一直在思考如何更好地了解消费者的需求,特别是在年轻化和线上消费趋势加强的母婴行业。根据《2023母婴行业数据报告合集》,短视频直播平台成为该行业新的增长点。报告合集显示,母婴商品的消费人数在2022年全年和2023年前两个月均呈快速增长趋......