单例模式-python代码实现-饿汉式、懒汉式

关键点:饿汉式、懒汉式、线程安全、线程单例

单例模式(Singleton Pattern)是最简单的设计模式,属于创建型模式

解决的根本问题:保证这个类有且只有一个实例对象,并且提供全局获取入口。比如 对文件的读写需要统一一个对象去管理

单例模式有哪些使用场景呢

  1. 访问资源冲突:比如读写同一个文件,使用单例可以只加对象级别的锁就可以
  2. 全局唯一:配置文件之类的,同一个窗体不重复创建两次

基本套路是私有化构造方法、提供getInstance方法获取实例。下面为单例模式的几种写法以及优缺点

饿汉式

饿汉式为在代码运行的时候,就创建出来这个对象,调取getInstance方法,就可以获取这个对象
python中的饿汉式可以直接在文件中创建对象,外部引用通过import的方式调用

class Singleton:
    def __init__(self):
        pass
singleton = Singleton()

外部引用

from Singleton import singleton

饿汉式的使用场景是 如果创建对象比较耗时,在调用其他的时候依赖这个类的创建,会导致这个方法的性能瓶颈是在这个类的创建上。而饿汉式单例,是在项目运行时就创建好对象,避免此问题。
注意网上流传的饿汉式的写法,我认为不是真正的饿汉式,下面我附上代码和我的理解

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        import time
        time.sleep(10)
        if not hasattr(Singleton, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

这样写,是满足了在调用初始化函数init之前创建对象,但是他还是在调用init的时候,触发生成这个对象,这样还是会在第一次调用其他方法的时候,出现创建此对象延迟的问题,因此我认为这种写法不是饿汉式。

懒汉式

饿汉式为调用getInstance方法时,再去创建类返回,最大的优点是延迟加载

class SingletonByLazy(object):
    """
    线程安全的懒汉式单例模式
    """
    _instance_lock = threading.Lock()

    @staticmethod
    def get_instance():
        if not hasattr(SingletonByLazy, "_instance"):
            with SingletonByLazy._instance_lock:
                if not hasattr(SingletonByLazy, "_instance"):
                    SingletonByLazy._instance = SingletonByLazy(*args, **kwargs)
        return SingletonByLazy._instance

这里因为线程安全和性能的考虑,检测了两次hasattr(SingletonByLazy, "_instance")

单例模式的问题

有时候,像id生成器,直接调用getId方法就好了,没必要获取那个对象
会隐藏依赖、继承关系
对代码的扩展性不够好

延伸问题

  • 线程唯一的单例模式:通过字典,key为线程id,value为对象,以此保证线程唯一
  • 进程、集群唯一的单例模式:通过文件来创建对象,保证文件的来保证数据唯一(java可以通过二进制文件来创造对象?待验证)
  • 多例模式

未完成事项

  • 线程安全的示意图
  • java、go代码实现
  • java通过文件创建类

你可能感兴趣的:(单例模式-python代码实现-饿汉式、懒汉式)