初识单例模式

单例模式含义

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

实现单例模式思路:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。

单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。

单例模式优点

  • 由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间
  • 全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用
  • 单例可长驻内存,减少系统开销

单例模式缺点

  • 单例模式的扩展是比较困难的
  • 赋于了单例以太多的职责,某种程度上违反单一职责原则
  • 单例模式是并发协作软件模块中需要最先完成的,因而其不利于测试
  • 单例模式在某种情况下会导致“资源瓶颈”

单例模式应用

  • 生成全局唯一的序列号
  • 访问全局复用的唯一资源,如磁盘、总线等
  • 单个对象占用的资源过多,如数据库等
  • 系统全局统一管理,如Windows下的Task Manager
  • 网站计数器(同步控制)

Python实现单例模式

使用模块

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

常见的场景即logging模块,写好一个日志类模块后,并实例化一个logger, 整个项目就调用这个logger

// logging_module.py
class LoggerMgr(object):
def foo(self):
pass mylogger = LoggerMgr()

__new__方法实现

class Singleton:
__instance = None
__init_flag = True def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
return cls.__instance def __init__(self, name):
if Singleton.__init_flag:
print("进行初始化")
self.name = name
Singleton.__init_flag = False

使用装饰器来获取单例对象

def singleton(cls):
__instance = {}
def getinstance(*args, **kwargs):
if cls not in __instance:
__instance[cls] = cls(*args, **kwargs)
return __instance[cls]
return getinstance @singleton
class MyClass:
a = 1

我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 keycls(*args, **kwargs) 作为 value 存到 instances 中,否则,直接返回 instances[cls]

使用metaclass元类创建单例

元类(metaclass)可以控制类的创建过程,它主要做三件事:

  1. 拦截类的创建
  2. 修改类的定义
  3. 返回修改后的类
class Singleton(type):
__instances = {} def __call__(cls, *args, **kwargs):
if cls not in cls.__instances:
cls.__instances[cls] = super().__call__()
return cls.__instances[cls] class MyClass(metaclass=Singleton):
def __init__(self):
self.blog = "blog"

python进阶(29)单例模式的更多相关文章

  1. 【python进阶】详解元类及其应用2

    前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使⽤type创建带有 ...

  2. Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究

    Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: ​ 反射的概念是由Smith在1982年首次提出的 ...

  3. Python学习day09 - Python进阶(3)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  4. python进阶_浅谈面向对象进阶

    python进阶_浅谈面向对象进阶 学了面向对象三大特性继承,多态,封装.今天我们看看面向对象的一些进阶内容,反射和一些类的内置函数. 一.isinstance和issubclass  class F ...

  5. Python进阶:函数式编程实例(附代码)

    Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...

  6. Python进阶 - 对象,名字以及绑定

    Python进阶 - 对象,名字以及绑定 1.一切皆对象 Python哲学: Python中一切皆对象 1.1 数据模型-对象,值以及类型 对象是Python对数据的抽象.Python程序中所有的数据 ...

  7. Python进阶-继承中的MRO与super

    Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...

  8. Python进阶 - 命名空间与作用域

    Python进阶 - 命名空间与作用域 写在前面 如非特别说明,下文均基于Python3 命名空间与作用于跟名字的绑定相关性很大,可以结合另一篇介绍Python名字.对象及其绑定的文章. 1. 命名空 ...

  9. python进阶学习笔记(一)

    python进阶部分要学习的内容: 学习目标: 1.函数式编程 1.1,什么是函数式编程 函数式编程是一种抽象计算的编程模式 不同语言的抽象层次不同: 函数式编程的特点: python支持的函数式编程 ...

  10. 【python进阶】Garbage collection垃圾回收2

    前言 在上一篇文章[python进阶]Garbage collection垃圾回收1,我们讲述了Garbage collection(GC垃圾回收),画说Ruby与Python垃圾回收,Python中 ...

随机推荐

  1. mysql_阻塞和死锁

    什么是阻塞 由于不同锁之间的兼容关系,造成一个事务需要等待另一个事务释放其所占用的资源的现象 称为 阻塞 如何发现阻塞 mysql_8.0 SELECT waiting_pid as '被阻塞的线程' ...

  2. [Python]-os模块-文件读取

    import os 在Python中,os模块用来处理文件路径,比较方便. os读取文件 在读取文件过程中,最常用的几个功能如下: os.listdir() 获取此目录下的所有目录名,并且存为列表.在 ...

  3. zabbix客户端无法上传数据

    昨天发现有一台Windows服务器无法向zabbix服务端汇报数据.经过检查Windows上的客户端日志,可以看到以下错误. 31976:20200206:154445.873 active chec ...

  4. Java 加载、编辑和保存WPS表格文件(.et/.ett)

    WPS表格文件是金山开发的专门用于处理表格数据的Office工具,属于WPS Office中WPS文字.WPS表格和WPS演示三大功能模块之一.通常以.et和.ett作为文件后缀.我们在通过后端来操作 ...

  5. X-Pack:创建阈值检查警报

    简单的事情应该简单(Simple things should be simple),这是Elastic {ON} '17的主题之一,Elastics收到了许多关于使用简单易用的UI创建警报的请求.事实 ...

  6. 防火墙:iptable和firewalld常用操作

    iptables //安装iptables-service yum install iptables-services //编辑config文件 vi /etc/sysconfig/iptables ...

  7. 获取Docker容器名称和ID

    docker ps --format "{{.Names}}" docker ps -q

  8. PAT (Basic Level) Practice 1009 说反话 分数 20

    给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出. 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串.字符串由若干单词和若干空格组成,其中单词是由英文字母(大小 ...

  9. 洛谷P3391 文艺平衡树 (Splay模板)

    模板题. 注意标记即可,另外,涉及区间翻转操作,记得设立首尾哨兵. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int ...

  10. 洛谷P1496 火烧赤壁 (模拟/离散化+差分)

    分析可知:将起点和终点按照从小到大的顺序排序,对答案不会产生影响 所以此时我们得到一种模拟做法: 1 #include<bits/stdc++.h> 2 using namespace s ...