重新深入理解单例模式

写在前面:

之前只是泛泛地理解,单例模式,趁着有些遗忘,再次深入理解下单例模式。顺便再赚点积分。

什么是单例模式?

单例模式是最简单的设计模式之一,属于创建型模式,它提供了一种创建对象的方式,确保只有单个对象被创建。这个设计模式主要目的是想在整个系统中只能出现类的一个实例,即一个类只有一个对象。 单例模式的解决的痛点就是节约资源,节省时间从两个方面看:

1.由于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级的对象而言,是很重要的.

2.因为不需要频繁创建对象,我们的GC压力也减轻了,而在GC中会有STW(stop the world),从这一方面也节约了GC的时间 单例模式的缺点:简单的单例模式设计开发都比较简单,但是复杂的单例模式需要考虑线程安全等并发问题,引入了部分复杂度。(GC垃圾回收)

简单来说,就是让你不管怎么实例化, 实例化几个,实际实际上都是对一个类操作,这跟多态是是互斥的,优点呢?就是节省资源和时间

应用场景:

  1. 资源共享下,避免由于资源操作时导致地性能损耗。
  2. 控制资源情况下, 方便资源之间的相互通信

下面介绍几种python实现单例的方法:

一 常规操作,利用__new__()

可以看到,无论实例化几次,都指向一个类, 每个实例都可以增加属性,实例可以拿到别的实例设置的属性。

class A(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = object.__new__(cls)
            return cls._instance
        else:
            return cls._instance



obj = A()
obj1 = A()
obj2 = A()
obj.attr = 'value'
obj2.attrs = 'lala'
obj1.attr = 'value1'
print(obj.attr)       # value1
print(obj1.attr)      # value1
print(obj2.attr)      # value1
print(obj2.attrs)     # lala
print(obj is obj1)    # True

非单例对比, 体现了python的多态。

class A(object):
    pass


obj = A()
obj1 = A()
obj2 = A()
obj.attr = 'value'
obj2.attrs = 'lala'
obj1.attr = 'value1'
print(obj.attr)       # value
print(obj1.attr)      # value1
# print(obj2.attr)      # 直接报错,是我A没有attr属性
print(obj2.attrs)     # lala
print(obj is obj1)    # False

二 利用python天生的特性

python天生就支持单例模式(生来就有,这让人很无奈啊)

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

其实我觉这种方法,太直白了,或者说直白的让人疑惑。就是你在py文件中写个类, 给它实例化一个实例,别的文件引用这个实例,,

确保一个类只有一个实例对象,,,

# myclass.py
class A(object):
    pass


obj = A()

# 在别的文件中引入

from myclass import obj

obj.attr = "lala"

 

三 根据装饰器

就是定义个空字典,字典没有这个类,就加进去,有的话,直接返回会原来的类

def single(cls):
    _instance = {}

    def getinstance(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]
    return getinstance


@single
class A(object):
    a = 1


obj = A()
obj1 = A()
obj.attr = "lal"     
print(obj1.attr)        # lal
print(obj is obj1)      # True

四 使用metaclss(元类), 这个就很哲学了,从元类开始操作

要做到:

  1. 拦截类的创建
  2. 修改类的定义
  3. 返回修改后的类
class Single(type):

    def __init__(self, *args, **kwargs):
        self._instance = None
        super(Single, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        # 这里的cls,即A类
        if cls._instance is None:
            cls._instance = super(Single, cls).__call__(*args, **kwargs)
        return cls._instance


class A(metaclass=Single):
    pass


obj = A()
obj1 = A()
obj.attr = "lal"
print(obj1.attr)     # lal
print(obj is obj1)   # True

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值