详解Python 单子的其他特性

  • Post category:Python

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 列表中。