初识单例模式

单例模式含义

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

实现单例模式思路:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用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. git hooks在业务中的使用

    起因 最近公司项目发生了一起线上事故,最后排查下来是配置文件的问题.项目里application.yml文件内会用@build.time@记录打包时的时间,但是这个写法是build-helper-ma ...

  2. csp每日习题

    欢迎加入:qq群号:1054587486 做题链接:https://csp.ccf.org.cn/csp/index.action?_access_code=1584494752035 点击模拟考试进 ...

  3. MQ的消息丢失/重复/积压的问题解决

    在我们实际的开发过程中,我们肯定会用到MQ中间件,常见的MQ中间件有kafka,RabbitMQ,RocketMQ.在使用的过程中,我们必须要考虑这样一个问题,在使用MQ的时候,我们怎么确保消息100 ...

  4. 第六章:Django 综合篇 - 10:消息框架 message

    在网页应用中,我们经常需要在处理完表单或其它类型的用户输入后,显示一个通知信息给用户. 对于这个需求,Django提供了基于Cookie或者会话的消息框架messages,无论是匿名用户还是认证的用户 ...

  5. Elasticsearch: Cerebro 用户界面介绍

  6. Docker安装prometheus

    # 拉取镜像 docker pull prom/prometheus:v2.22.0 # 创建配置文件 mkdir -p /opt/prometheus/ cd /opt/prometheus vim ...

  7. 5_SpringMVC

    一. 什么是MVC框架 MVC全名是Model View Controller, 是模型(model), 视图(view), 控制器(controller)的缩写, 一种软件设计典范, 用一种业务逻辑 ...

  8. Java删除word合并单元格时的重复值

    Spire.Doc提供了Table.applyVerticalMerge()方法来垂直合并word文档里面的表格单元格,Table.applyHorizontalMerge()方法来水平合并表格单元格 ...

  9. Podman容器基础(二)

    Podman容器技术基础(二) 目录 Podman容器技术基础(二) 容器的使用 用户操作 用户配置文件 容器卷 容器的使用 运行一个容器 [root@cent1 ~]# podman pull ht ...

  10. liunx文件定期本地备份、异地备份、删除备份脚本

    导航 一.背景二.依赖功能介绍三.本地备份脚本四.异地备份脚本五.定期删除备份六.github脚本地址 - - - - - - - - - - 分割线 - - - - - - - - - - 一.背景 ...