Python 设计模式——单例模式
单例模式即确保类有且只有一个特定类型的对象,并提供全局访问点。因此通常用于日志记录、数据库操作、打印机后台处理程序等。这些程序在运行过程中只生成一个实例,避免对同一资源产生相互冲突的请求。
特点:
- 确保类有且只有一个对象被创建
- 为唯一对象提供访问点,令其可被全局访问
- 控制共享资源的并行访问
经典单例模式
class Singleton(object):
def __new__(cls, name):
if not hasattr(cls, 'instance'):
cls.instance = super().__new__(cls)
return cls.instance def __init__(self, name):
self.name = name s1 = Singleton('Singleton1')
print(s1)
# => <__main__.Singleton object at 0x7efc1b006220>
print(s1.name)
# => Singleton1 s2 = Singleton('Singleton2')
print(s2)
# => <__main__.Singleton object at 0x7efc1b006220>
print(s2.name)
# => Singleton2
print(s1.name)
# => Singleton2
在上面的代码中,通过定义 __new__ 方法控制对象的创建。方法 hasattr 则用于检查对象 cls 是否具有 instance 属性(即确认该类是否已经生成了一个对象)。若 instance 属性不存在,则使用 super().__new__() 方法创建新的实例;若 instance 属性存在,则分配已有的实例给变量。
因此当 s2 = Singleton('Singleton2') 执行时,hasattr 发现对象实例已存在(s1),因此直接将已有的对象分配给 s2。s1 和 s2 实际是同一个对象实例。
Monostate(单态)模式
Monostate 模式即类的所有实例对象共享相同的状态。
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state b = Borg()
b1 = Borg() print(b is b1) # => False
b.x = 4
print(b.x) # => 4
print(b1.x) # => 4
b1.x = 6
print(b1.x) # => 6
print(b.x) # => 6
在上述代码中,通过将类变量 __shared_state 赋值给实例变量 __dict__ ( __dict__ 变量用于存储实例对象的属性等状态),使得类生成的所有对象实例都共享同一状态。
即 b 和 b1 是 Borg 类创建的不同的实例对象,但用于保存实例状态的 b.__dict__ 和 b1.__dict__ 却是相同的(即都是 Borg.__shared_state )。因此 b 的属性 x 若发生改变,同样的变化也会体现到 b1 中。
也可以通过修改 __new__ 方法来实现 Borg 模式:
class Borg:
__shared_state = {}
def __new__(cls, name):
obj = super().__new__(cls)
obj.__dict__ = cls.__shared_state
return obj def __init__(self, name):
self.name = name b1 = Borg('Borg1')
print(b1.name) # => Borg1
b2 = Borg('Borg2')
print(b2.name) # => Borg2
print(b1.name) # => Borg2
b1.name = 'Borg'
print(b1.name) # => Borg
print(b2.name) # => Borg
print(b1 is b2) # => False
通过元类实现单例模式
class MetaSingleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None def __call__(self, *args, **kwargs):
if not self.__instance:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance class Logger(metaclass=MetaSingleton):
pass logger1 = Logger()
logger2 = Logger()
print(logger1, logger2)
# => <__main__.Logger object at 0x7fac8af577c0> <__main__.Logger object at
# 0x7fac8af577c0>
print(logger1 is logger2) # => True
单例模式的实际应用
DB 操作
import sqlite3 class MetaSingleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None def __call__(self, *args, **kwargs):
if not self.__instance:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance class Database(metaclass=MetaSingleton):
connection = None
def connect(self):
if self.connection is None:
self.connection = sqlite3.connect("db.sqlite3")
self.cursorobj = self.connection.cursor()
return self.cursorobj db1 = Database().connect()
db2 = Database().connect() print(db1, db2)
# => <sqlite3.Cursor object at 0x7f810d6f8260> <sqlite3.Cursor object at
# 0x7f810d6f8260>
print(db1 is db2)
# => True
监控服务
class HealthCheck:
_instance = None
def __new__(cls, *args, **kwargs):
if not HealthCheck._instance:
HealthCheck._instance = super().__new__(cls, *args, **kwargs)
return HealthCheck._instance def __init__(self):
self._servers = [] def addServer(self):
self._servers.append("Server 1")
self._servers.append("Server 2")
self._servers.append("Server 3")
self._servers.append("Server 4") def changeServer(self):
self._servers.pop()
self._servers.append("Server 5") hc1 = HealthCheck()
hc2 = HealthCheck() hc1.addServer()
print("Schedule health check for servers (1) ...")
for i in range(4):
print("Checking ", hc1._servers[i]) hc2.changeServer()
print("Schedule health check for servers (2) ...")
for i in range(4):
print("Checking ", hc2._servers[i]) # => Schedule health check for servers (1) ...
# => Checking Server 1
# => Checking Server 2
# => Checking Server 3
# => Checking Server 4
# => Schedule health check for servers (2) ...
# => Checking Server 1
# => Checking Server 2
# => Checking Server 3
# => Checking Server 5
想学习更多关于python的知识可以加我
QQ:2955637827
Python 设计模式——单例模式的更多相关文章
- 浅谈Python设计模式 - 单例模式
本篇主要介绍一下关于Python的单例模式,即让一个类对象有且只有一个实例化对象. 一.使用__new__方法(基类) 要实现单例模式,即为了让一个类只能实例化一个实例,那么我们可以去想:既然限制创建 ...
- python设计模式-单例模式
单例模式应用场景 代码的设计模式共有25种,设计模式其实是代码无关的.其目的是基于OOP的思想,不同应用场景应用不同的设计模式,从而达到简化代码.利于扩展.提示性能等目的.本文简述Python实现的单 ...
- Python设计模式——单例模式
单例模式是日常应用中最广泛的模式了,其目的就是令到单个进程中只存在一个类的实例,从而可以实现数据的共享,节省系统开销,防止io阻塞等等 但是在多进程的应用中,单例模式就实现不了了,例如一些web应用, ...
- Python学习:19.Python设计模式-单例模式
一.单例模式存在的意义 在这里的单例就是只有一个实例(这里的实例就像在面向对象的时候,创建了一个对象也可以说创建了一个实例),只用一个实例进行程序设计,首先我们可以了解一下什么时候不适合使用单例模式, ...
- Python设计模式--单例模式(懒汉式)
1. 单例模式 --> 单一(唯一)的实例. 在整个运行时间内, 内存中只有一个对象, 一般该对象涉及网络,资源等操作. 2. 单例模式一般分为懒汉式和饿汉式 懒汉式内存占用更加合理. 3. 调 ...
- Python学习:Python设计模式-单例模式
一.单例模式存在的意义 在这里的单例就是只有一个实例(这里的实例就像在面向对象的时候,创建了一个对象也可以说创建了一个实例),只用一个实例进行程序设计,首先我们可以了解一下什么时候不适合使用单例模式, ...
- Python——设计模式——单例模式
一个类始终只有一个实例 当你第一次实例化这个类的时候,就创建一个实例化得对象 当你之后再来实例化的时候,就用之前创建的对象 class A: __instance = False def __ini_ ...
- python设计模式之单例模式(一)
前言 单例模式是创建模式中比较常见和常用的模式,在程序执行的整个生命周期只存在一个实例对象. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python ...
- python设计模式之单例模式(二)
上次我们简单了解了一下什么是单例模式,今天我们继续探究.上次的内容点这 python设计模式之单例模式(一) 上次们讨论的是GoF的单例设计模式,该模式是指:一个类有且只有一个对象.通常我们需要的是让 ...
随机推荐
- Apiview+serallizers
1.APIVIEW使用 https://www.cnblogs.com/xiaonq/p/10124104.html ModelVIewSet是对APIView封装 ModelSerializer是对 ...
- 浅谈AsyncLocal,我们应该知道的那些事儿
前言 最近查看有关框架源码,发现AsyncLocal这玩意水还挺深,于是花了一点功夫去研究,同时对比ThreadLocal说明二者区别以及在何时场景下使用AsyncLocal或ThreadLocal. ...
- vue组建通信
父组件 <template> <div> <zi :str="str" @change_fu="getzi"></zi ...
- chrome浏览器查看当前页面cookie
方法一:点进去设置--高级--网站设置--权限cookie--查找所有cookie和网站数据,就可以看到所有的cookie信息了,举例: 方法二:键盘F12,找到network--点击Doc(如果没有 ...
- 使用SpringSecurity Oauth2.0实现自定义鉴权中心
Oauth2.0是什么不在赘述,本文主要介绍如何使用SpringSecurity Oauth2.0实现自定义的用户校验 1.鉴权中心服务 首先,列举一下我们需要用到的依赖,本文采用的是数据库保存用户信 ...
- 安装pillow报错处理
sudo python3 pip install pillow 报错:The headers or library files could not be found for jpeg,... 解决:安 ...
- Python之【模块】
双层装饰器 一个函数可以被多个装饰器装饰: 多层装饰器的本质是:嵌套: 执行规则是:解释自下而上,执行自上而下 •简单的用户权限验证程序: USE_INFO = {} # 初始化一个字典,用户存放用户 ...
- 学JAVA的艰难之路
周五回家了,这两天也没有更新代码系列,很抱歉,之后会补上.今天刚到宿舍,写了会代码,想用一个数组的从键盘输入,再也弄不好了,最终在我不断的翻之前写的代码,终于是找到了一个例子,真的不容易,编程这东西, ...
- 【开发工具】 使用 Postman 进行接口测试 (配置全局 token,JWT可用)
在前后端分离开发的项目中,使用postman来做接口测试会方便很多,然而因为JWT的鉴权,导致每半小时token都要更新一下,使测试变的很麻烦. 如果把token设置为全局变量,方便做测试,每次自动获 ...
- 二分查找——没有想象中的容易(详解各种变式,超深度理解,c++)
int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 注意 while(le ...