Python 中的单例(Singleton)指的是一个类只能创建且仅创建一个对象的设计模式,这种模式在实际开发中非常实用。Python 中的单例模式有多种实现方式,本文将从概念、实现方法、示例等多个方面展开讲解。
概念
单例模式是一种创建型设计模式,用于限制某个类仅能够创建一个对象。在 Python 中,要实现单例模式有多种方法,但这些方法都有相似的特点,即只允许创建一个实例,后续的调用都是返回该实例。
实现方法
懒汉式单例模式
使用的时候才创建,是一种比较常见的单例实现方式。这种方式的实现非常简单,只需要在类中定义一个私有的类属性,确保该属性只会在第一次被访问时才会被创建,之后再次访问该属性时便直接返回该属性对应的对象即可。
下面是一个懒汉式单例模式的示例代码:
class Singleton:
__instance = None
@classmethod
def get_instance(cls):
if cls.__instance is None:
cls.__instance = Singleton()
return cls.__instance
在上述代码中,我们定义了一个私有的 __instance
类属性,并通过 get_instance()
方法返回该属性对应的实例对象。如果 __instance
不存在,则先创建一个新对象,再返回该对象。
饿汉式单例模式
在类初始化时就创建一个对象,是一种比较常见的单例实现方式。这种方式的实现较为简单,只需要在类定义时就直接定义一个类属性,并在类实例化时返回该属性对应的对象即可。
下面是一个饿汉式单例模式的示例代码:
class Singleton:
__instance = Singleton()
@classmethod
def get_instance(cls):
return cls.__instance
在上述代码中,我们定义了一个私有的 __instance
类属性,并在类定义时就创建了一个实例对象。随后通过 get_instance()
方法返回该属性对应的实例对象。
示例说明
示例一:线程池
在使用线程池时,一个常见的需求是希望线程池全局只存在一个实例对象,且可以在多个线程中共享该实例。这时我们可以使用单例模式来实现线程池的单例对象。
下面是一个基于饿汉式单例模式的线程池实例代码:
import threading
class ThreadPool:
__instance = ThreadPool()
def __init__(self):
self.__lock = threading.Lock()
def submit(self, fn, *args, **kwargs):
with self.__lock:
# TODO: 实现线程池的提交方法
pass
@classmethod
def get_instance(cls):
return cls.__instance
在上述代码中,我们通过 __instance
属性定义了一个单例对象,保证线程池只有一个实例。实例化时需要注意加锁操作,防止多个线程同时实例化线程池。
示例二:窗口管理器
在 GUI 应用程序开发中,我们常常需要使用一个窗口管理器来管理所有已打开的窗口对象。为避免同时打开多个相同的窗口,我们希望全局只存在一个窗口管理器实例对象,且需要支持在多个窗口对象之间共享该实例。
下面是一个基于懒汉式单例模式的窗口管理器实例代码:
class WindowManager:
__instance = None
def __init__(self):
self.__windows = []
def add_window(self, window):
self.__windows.append(window)
@classmethod
def get_instance(cls):
if cls.__instance is None:
cls.__instance = WindowManager()
return cls.__instance
在上述代码中,我们定义了一个 __windows
私有属性用于保存所有打开的窗口对象,并通过 get_instance()
方法实现单例模式。当 __instance
不存在时,创建一个新窗口管理器对象。在 add_window()
方法中,将其中一个窗口对象添加至 __windows
列表中。