单例模式
python的单例模式,其目的是为一个确保一个类仅有一个实例,并提供一个全局访问点来获取该实例。
单例模式的目的
- 控制资源的使用:通过确保只创建一个实例,单例模式可以避免对系统资源的重复使用和消耗
- 保证数据的一致性:单例模式确保所有对单例实例的访问都是对同一个对象的访问,这有助于从不同的程序路径对数据进行一致的读写。
- 全局访问点: 单例模式提供了一个全局访问点供外部访问其唯一的实例,这就像一个全部变量,但更安全
单例模式的示例用途
1.日志记录器:日期记录器通常使用单例模式,因为他通常需要在应用程序中的多个地方进访问,而且无论在何处访问,都应该是相同的日志记录实例,以便于集中的管理日志和记录日志
使用类变量
import logging
class LoggerSingleton:
_instance = None
@classmethod
def get_instance(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = logging.getLogger("Mylogger")
cls._instance.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console_handler.setFormatter(formatter)
cls._instance.addHandler(console_handler)
return cls._instance
logger = LoggerSingleton.get_instance()
logger.debug("asd")
使用__new__方法
import logging
class LoggerSingleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(LoggerSingleton, cls).__new__(cls, *args, **kwargs)
cls._instance = logging.getLogger("Mylogger")
cls._instance.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console_handler.setFormatter(formatter)
cls._instance.addHandler(console_handler)
return cls._instance
logger = LoggerSingleton()
logger.debug("asd")
2.配置文件的读取,如果应用程序从配置文件中(json文件,xml文件等)读取启动配置,使用单例模式可以确保整个应用程序使用的配置信息是统一䣌,并且配置文件仅被读取过一次,而不是每次访问配置时候,都需要重新读取
使用__new__方法
class ConfigSingleton:
_instance = None
def __new__(cls, file_path, *args, **kwargs):
if cls._instance in None:
cls._instance = super(ConfigSingleton, cls).__new__(cls, *args, **kwargs)
with open(file_path, "r") as f:
cls._instance = f.read()
return cls._instance
coinfig = ConfigSingleton("config.txt")
使用类方法
class ConfigSingleton:
_instance = None
@classmethod
def get_instance(cls, file_path):
if cls._instance in None:
with open(file_path, "r") as f:
cls._instance = f.read()
return cls._instance
coinfig = ConfigSingleton.get_instance("config.txt")
3.数据库连接池:数据库连接是一种稀缺的资源,使用单例模式管理数据库连接池可以确保应用程序中的数据库连接的有效管理和重用
使用__new__方法
import pymysql
class MysqlSingleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(MysqlSingleton, cls).__new__(cls, *args, **kwargs)
cls._instance = pymysql.connect(
host='your_host',
user='your_user',
password='your_password',
db='your_db',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
return cls._instance
mysql_con = MysqlSingleton()
cursor = mysql_con.cursor()
使用类方法
import pymysql
class MysqlSingleton:
_instance = None
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = pymysql.connect(
host='your_host',
user='your_user',
password='your_password',
db='your_db',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
return cls._instance
mysql_con = MysqlSingleton.get_instance()
cursor = mysql_con.cursor()
__new__方法中有一行代码时调用父类的,具体怎么解释?
- 在使用__new__方法实现单例模式时候"““super(MysqlSingleton, cls).new(cls,*args, **kwargs)””"这行代码的作用是调用父类的__new__方法来创建一个实例。这是因为__new__方法是一个特殊的静态方法,他负责创建并返回一个新的实例。
- ”super(MysqlSingleton, cls)“这部分嗲用super()函数,返回父类(即object,因为绝大数的类都继承object)的一个代理对象
- new(cls,*args,**kwargs)这部分对父类的__new__方法的调用,他负责创建一个新的实例。cls参数是当前类(MysqlSingleton)其他参数都是传递给__new__的方法外的任何参数
- 在单例模式的上下文中,这行代码的作用实在第一次实例化的单例模式的时候创建一个新的实例。创建设置后,这个实例会被保存在类变量(_instance)中。随后对类的任何进一步实例化尝试都会返回这个已经创建的实例,从而确保类的全局唯一性。
- ‘super(MysqlSingleton, cls).new(cls,*args,**kwargs)’这行代码是单例模式实现中创建唯一实例的关键步骤。他确保了使用__new__方法创建实例的正确性,并且旨在第一次调用是创建一个实例,后续调用返回的都是这个已经创建按的实例