学习之面试题:单例模式

什么是单例模式?

单例模式是一种设计模式,它保证一个类仅有一个实例,并提供一个全局访问点用于访问该实例。其主要目的是控制共享资源的访问。

为什么我们需要单例模式?

单例模式可以用于控制资源的消耗,避免频繁创建和销毁对象,同时也可以简化系统配置,使得某些类的对象在整个系统中具有唯一的实例,比如日志对象、数据库连接等。

如何在 Python 中实现单例模式?

python 复制代码
下面是一些常见的实现方式:

方法一:使用模块
Python 模块本身就是单例的,所以在一个模块中定义的类可以被多个脚本共享。

方法二:使用 __new__ 方法
重写类的 __new__ 方法来控制实例的创建过程,确保只创建一次实例。

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

singleton_instance = 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

my_instance = MyClass()
方法四:使用元类(MetaClass)
利用Python的元编程特性来控制类的行为。

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class MyClass(metaclass=Singleton):
    pass

my_instance = MyClass()


方法五:使用线程局部存储(Thread Local Storage)
如果需要在多线程环境中使用单例,可以考虑使用 threading.local 来保证线程安全。


import threading

class Singleton(object):
    _instance_lock = threading.Lock()
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._instance_lock:
                if not cls._instance:
                    cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

singleton_instance = Singleton()

在多线程环境中如何保证单例模式的安全性?

在多线程环境中,为了防止多个线程同时进入 if instance is None 判断条件的情况,可以使用锁机制(如 threading.Lock() 或 threading.RLock())来确保线程安全。

单例模式有哪些优缺点?

优点:

控制实例的产生,节省系统资源。

提供了一个全局访问点,方便获取对象实例。

缺点:

违背了单一职责原则,将类的实例化与业务逻辑混在一起。

增加了系统的复杂度,降低了程序的可测试性。

过度使用会导致系统难以理解和维护。

你能给出一个简单的单例模式实现的例子吗?

python 复制代码
Python
深色版本
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 使用例子
s1 = Singleton()
s2 = Singleton()
assert s1 is s2

单例模式是否适用于所有情况?

不一定,单例模式的应用场景有限,通常用于那些需要频繁访问且创建成本较高的对象。在现代软件开发中,依赖注入和 IoC 容器等技术逐渐成为更好的替代方案。

相关推荐
小小de风呀2 小时前
de风——【从零开始学习Linux】(九):进程基础 —— 从冯诺依曼体系到 fork 创建进程
linux·学习
李某学编程2 小时前
基于ARM的微机原理学习笔记(一)
arm开发·笔记·学习
Song_RsHt3 小时前
Redis 与微服务,什么场景下无可替代
java·redis·后端·学习·微服务
~kiss~5 小时前
PRO-LONG: Programmatic Memory Enables Long-Horizon Reasoning 程序式记忆赋能长程推理
学习
程序猿编码5 小时前
不依赖 vLLM/llama.cpp:一套面向学习的 DeepSeek-R1 CUDA 推理实现
c++·学习·语言模型·llama·vllm·大模型推理
ms72wx6 小时前
Docker 命令学习笔记:从入门到进阶的实战指南
笔记·学习·docker
外收内放7 小时前
FastAPI猜字谜实战(4):让AI主持人开口
开发语言·python·学习·fastapi
叶子野格7 小时前
《JAVA学习:前置知识》
学习
小猪佩奇TONY8 小时前
Linux 内核学习(19) --- linux swap 机制
linux·学习·swap·kswapd
andrsted8 小时前
企业培训时间难统一?练题簿让在线免费刷题与培训考核更好安排
学习·微信小程序·小程序·学习方法·刷题