Python设计模式(3)--单例模式

1. 理解单例设计模式(Singleton Pattern)

单例模式的机制是确保类有且只有一个特定类型的对象,并且提供全局的访问点。归纳如下:

  • 确保类有且只有一个对象被创建
  • 为对象提供一个访问点,以使程序可以全局访问该对象
  • 控制共享资源的并行访问

需要注意的是,单例模式存在线程安全问题,常用解决办法是添加线程锁,

实现单例模式的一个简单方法是,使构造函数私有化,并创建一个静态方法来完成对象的初始化,这样,对象在第一次调用时创建,此后,这个类返回同一个对象。

2. 常见的三种单例模式,及其实现
2.1 经典的单例模式实现

实现思路:

  1. 只允许Singleton类生成一个实例
  2. 如果已经有了一个实例了,重复提供同一个实例对象

代码实现:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

# 结果测试
s1 = Singleton()
print(s1)
s2 = Singleton()
print(s2)

通过覆盖__new__方法来控制对象的创建。对象s1就是由__new__方法创建的,但在创建之前,该方法会检查对象是否已经创建。

2.2 模块级别的单例模式

在python中,默认情况下,所有的模块都是单例模式,这是由python的导包机制所决定的。

python导包机制如下:

  1. 检查一个python模块是否已经导入
  2. 如果已经导入,返回该模块对象,如果还没有导入,则导入该模块,并实例化
  3. 因此,在模块被导入的时候,他就会被初始化。当同一个模块被再次导入的时候,它不会再次初始化,而是返回之前初始化的模块对象。
2.3 单例模式中的懒汉式实例化

懒汉单例模式在最开始并不会完成创建实例对象,而是在需要使用的时候调用getInstance方法时才调用。这种模式主要用在:当我们创建一个对象或者导入一个模块对象时,并不会马上用到它,懒汉单例模式此时并不会真正地创建这个对象,而是等到需要时才会创建,可以节约资源。

class Singleton(object):
    __instance = None
    def __init__(self):
        if not Singleton.__instance:
            print("__init__ 方法被调用...")
        else:
            print("对象已经被创建:", self.getInstance())
            self = Singleton.__instance

    @classmethod
    def getInstance(cls):
        if not cls.__instance:
            cls.__instance = Singleton()
        return cls.__instance

# 结果测试
s1 = Singleton()
print("创建对象:",Singleton.getInstance())
s2 = Singleton()
3. 使用元类创建单例模式

元类:元类是一个类的类,是用来创建类的‘类’

由于元类对类的创建和对象的实例化有更多的控制权,所以,他可以用于创建单例,为了控制类的创建和初始化,元类将覆盖__new__和__init__方法。

代码实现:

class MateSingleton(type):
    _instance = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instance:
            cls._instance[cls] = super(MateSingleton, cls).__call__(*args, **kwargs)
        return cls._instance


class Singleton(metaclass=MateSingleton):
    pass

# 结果测试
s1 = Singleton()
s2 = Singleton()
print(s1,s2)  
#{<class '__main__.Singleton'>: <__main__.Singleton object at 0x0000016F6CF06390>} {<class '__main__.Singleton'>: <__main__.Singleton object at 0x0000016F6CF06390>}
4. 单例模式的一个变种–Monostate(单态)单例模式

普通的单例模式机制是让一个类有且只有一个对象,而Monistate模式的核心思想是让实例对象共享相同的状态,该模式建议开发人员应该关注对象的状态和行为,而不是同一性。

代码实现:

class Monostate(object):
    __shared_state={}
    def __init__(self):
        self.__dict__ = self.__shared_state

# 结果测试
b1 = Monostate()
b2 = Monostate()
b1.name = "chris"

print("b1:",b1)  # b1: <__main__.Borg object at 0x000001DB7DA4A128>
print("b2:",b2)  # b2: <__main__.Borg object at 0x000001DB7DA4A1D0>
print("b1的属性:",b1.__dict__)  # b1的属性: {'name': 'chris'}
print("b2的属性:",b2.__dict__)  # b2的属性: {'name': 'chris'}
5.总结–单例模式的缺点
  • 存在线程安全问题
  • 全局变量可能会在某个地方被修改,而开发人员因为没有注意到单例模式的修改,将该变量用到了程序其他地方,会引起一系列数据错误
  • 由于单例只创建一个对象,可能会对同一对象创建多个引用。
  • 所有依赖于全局变量的类都会由于一个类的改变而紧密耦合为全局数据,从而可能无意中影响另一个类
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值