下面是 Python 实现单例模式的 5 种方法的详细攻略。
什么是单例模式?
单例模式是一种常见的设计模式,它保证一个类只能创建一个实例,并提供一个全局访问该实例的方式。
Python 实现单例模式的 5 种方法
方法一:使用模块
Python 中的模块加载是线程安全的,因此将实例化代码放在模块级别的变量中,可以保证只有一个实例会被创建。
# singleton.py
class Singleton(object):
def __new__(cls):
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls)
return cls._instance
这种方法需要将所有的单例类代码放在一个模块中,然后使用模块导入来获得单例对象。例如:
from singleton import Singleton
singleton = Singleton()
方法二:使用装饰器
使用装饰器将实例化代码封装在闭包中,然后用一个字典变量存储闭包对象和单例对象的对应关系,保证每个类只有一个实例对象。
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class MyClass(object):
pass
方法三:使用元类
Python 中的类也是对象,因此可以使用元类来实现单例模式。元类是类的类,可以用来控制类的创建过程和行为。
class Singleton(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super().__call__(*args, **kwargs)
return cls._instance
class MyClass(metaclass=Singleton):
pass
方法四:使用基类
将单例模式的实现封装到一个基类中,并在每个需要单例模式的类中继承该基类。
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
class MyClass(Singleton):
pass
方法五:使用模板方法
使用模板方法模式将单例模式封装到一个基类中,并在每个子类中实现模板方法。
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
class MyClass(Singleton):
def __init__(self, arg):
self.arg = arg
@classmethod
def create_singleton(cls, arg):
if not cls._instance:
cls._instance = cls(arg)
return cls._instance
这种方法需要子类实现一个静态方法或类方法来创建单例对象,例如:
my_object = MyClass.create_singleton('argument')
示例说明
下面我们来看两个关于单例模式的示例。
示例一:程序日志
在一个程序中,我们通常需要记录一些日志信息,而记录日志的类只需要一个实例即可。因此可以使用单例模式来实现日志记录类。
import logging
class SingletonLogger(object):
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
cls._instance.logger = logging.getLogger(__name__)
return cls._instance
def log(self, message):
self.logger.info(message)
在其他模块中使用 Logger 对象时,只需要导入 SingletonLogger 类并调用 log 方法即可。
from singleton_logger import SingletonLogger
logger = SingletonLogger()
logger.log('Logging message')
示例二:数据库连接池
在 Web 应用开发中,为了提高数据库访问效率,我们通常会使用连接池来管理数据库连接。连接池只需要一个实例即可,可以使用单例模式来实现。
import MySQLdb
from dbutils.pooled_db import PooledDB
class SingletonDatabase(object):
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
cls._instance.pool = PooledDB(
creator=MySQLdb,
use_unicode=True,
db='test',
user='user',
password='password',
host='localhost',
port=3306,
charset='utf8mb4',
maxconnections=100,
blocking=True
)
return cls._instance
def get_connection(self):
return self.pool.connection()
def close_connection(self, conn):
conn.close()
在其他模块中使用数据库连接池时,只需要导入 SingletonDatabase 类并调用 get_connection 方法获取数据库连接即可。
from singleton_database import SingletonDatabase
db = SingletonDatabase()
conn = db.get_connection()
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
results = cursor.fetchall()
db.close_connection(conn)
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python实现单例模式的5种方法 - Python技术站