Python 之单例模式

简介:单例模式(Singleton Pattern) 是最简单的设计模式之一,属于创建型的设计模式。单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,不需要实例化该类的对象。

特性

- 单例类只有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。

优点

- 在内存中只有一个实例,减少内存的开销,尤其是频繁的创建和销毁实例
- 避免对资源的多重占用

缺点

  • 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

应用场景

  • 资源共享的情况下,避免由于资源操作时导致的性能损耗等。如日志文件,应用配置
  • 控制资源的情况下,方便资源之间的互相通信。如线程池等。

实现核心原理

重写类方法中的____new____方法

  • 使用类名()创建对象时,Python的解释器首先会调用____new____方法为对象分配空间

  • ____new____是一个由object基类提供的内置静态方法,主要作用有:1.分配内存为对象分配空间;2.返回对象的引用

  • Python的解释器获得对象的引用后,将引用作为第一个参数,传递给____init____方法

代码示例

  1. 懒汉式 非线程安全的单例模式

    这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁synchronized,所以严格意义上它并不算单例模式。

    class Singleton(object):
      instance = None
      
      def __new__(cls,name,age):
        if not cls.instance:
          cls.instance = object.__new__(cls)
        return cls.instance
    test1 = Singleton("zhangsan",18)
    test2 = Singleton("lisi",18)
    
    print(id(test1))
    print(id(test2))
    
    test1.age = 30
    print(test2.age)
    

    运行结果:

    4389937560
    4389937560
    30
    
    Process finished with exit code 0
    
  2. 懒汉式 线程安全的单例

    这种方式具备很好的lazy loading 能够在多线程中很好的工作,但是,效率很低,99%情况下不需要同步。

    优点:第一次调用才初始化,避免内存浪费

    缺点:必须加锁synchronized 才能保证单例,但加锁会影响效率

    import threading
    
    
    def synchronized(func):
        func.__lock__ = threading.Lock()
    
        def lock_func(*args, **kwargs):
            with func.__lock__:
                return func(*args, **kwargs)
    
        return lock_func
    
    
    class Singleton(object):
        instance = None
    
        @synchronized
        def __new__(cls):
            if not cls.instance:
                cls.instance = super(Singleton, cls).__new__(cls)
            return cls.instance
    
    
    test1 = Singleton()
    test2 = Singleton()
    
    print(id(test1))
    print(id(test2))
    
    

    运行结果:

    4554555800
    4554555800
    
    Process finished with exit code 0
    

知识补充

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

#mysingleton.py
class Singleton(object):
  def foo(self):
    pass
  
singleton = Singleton()

将上面的代码保存在文件mysingleton.py中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象

from xxxx import singleton

每天多努力那么一点点,积少成多

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • python设计模式中的 单例模式:单例模式可以通过__new__ 方法实现,而__new__ 方法一般用于继承不...
    烟肆酒家阅读 854评论 4 4
  • 相信大家都知道设计模式,听的最多的也应该是单例设计模式,这种模式也是在开发中用的最多的设计模式,可能有很多人会写几...
    之后_90阅读 429评论 0 0
  • 一.什么是单例模式 单例模式的定义:确保一个类只有一个实例,并提供一个访问他的全局访问点。单例模式是几个设计模式中...
    Geeks_Liu阅读 2,252评论 0 10
  • 定义 一个类只有一个实例,自行实例化并提供给整个系统。 基本思路 将该类构造函数私有化,并通过静态方法获取一个唯一...
    剧透下阅读 258评论 0 0
  • 医者姓名:梁军 日期:20180821 1.陈述:(症状描述) 李某,女,43岁,左乳腺硬块(左侧)3年,医生要做...
    同道心灵梁军阅读 2,341评论 0 0