单例模式

单例模式的定义与特点

单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。单例模式有 3 个特点:

  • 单例类只有一个实例对象;
  • 该单例对象必须由单例类自行创建;
  • 单例类对外提供一个访问该单例的全局访问点;

单例模式的结构和实现

单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。

单例模式的结构

  • 单例类:包含一个实例且能自行创建这个实例的类
  • 访问类:使用单例的类

结构如图所示:

图1 单例模式的结构图

单例模式的实现

1.懒汉式单例

该模式的特点是类加载时没有生成单例,只有当一次调用get_instance方法时才创建这个单例,代码实现如下:

class Singleton(object):
    __instance = None
    def __init__(self):
        if not self.__instance:
            print("调用__init__, 实例未创建")
        else:
            print("调用__init__,实例已经创建:", __instance)
    @classmethod
    def get_instance(cls):
        if not cls.__instance:
            cls.__instance = Singleton()
        return cls.__instance

优点:资源利用合理,不调用get_instance方法不创建单例对象。缺点:线程不安全,多线程时可能会获取到不同单例对象的情况。解决办法是加互斥锁,但会降低效率
线程安全的单例

2.饿汉式单例

该模式的特点是类一旦加载就创建一个单例,保证在调用getinstance方法之前单例已经存在了,实现代码如下:

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

优点:线程安全;在类实例化前创建好一个静态对象,调用时反应速度快;直接执行其他方法和静态方法,单例实例不会初始化。缺点:不管使用与否,实例化前就初始化静态对象,资源浪费

3.线程安全的单例

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, *args, **kwargs):
       if cls.instance is None:
           cls.instance = super().__new__(cls)
        return cls.instance

    def __init__(self, num):
        self.a = num + 5

单例模式的应用场景

前面分析了单例模式的结构与特点,以下是它通常适用的场景的特点。

  • 在应用场景中,某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
  • 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
  • 当某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。

   转载规则


《单例模式》 ForwardPeng 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
原型模式 原型模式
原型模式的特点原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
2020-05-11
下一篇 
NumPy学习 NumPy学习
ndarray数组的创建首先导入numpy包: import numpy as np 通过np.+Tab键查看可使用的函数,在对应函数加上?,再运行,就可以很方便地看到如何使用函数的帮助信息。NumPy封装了一个新的数据类型ndarra
  目录