Python单例模式的代码实现和原理

Python单例设计模式的代码实现

python 复制代码
import threading
import time


class Singleton(object):  
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance



class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()



class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)


if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()

这段代码实现并演示了Python中的单例模式,下面详细解释其代码实现和原理:

代码实现

单例类 Singleton 的定义:

python 复制代码
class Singleton(object):  
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance
  • new 是Python类的一个特殊方法,用于创建并返回一个实例化对象。在单例模式里,它首先检查类属性 _instance 是否存在。如果不存在,就通过调用父类的 new 方法来创建一个新实例,并将其赋值给 _instance ;如果已经存在,直接返回这个已有的实例。
    Bus 类:
python 复制代码
class Bus(Singleton):
    lock = threading.RLock()

    def sendData(self, data):
        self.lock.acquire()
        time.sleep(3)
        print("Sending Signal Data...", data)
        self.lock.release()
  • Bus 类继承自 Singleton 类,也就继承了单例的特性。它定义了一个线程锁 lock ,用于在多线程环境下同步访问资源, sendData 方法用于发送数据,通过获取锁、模拟耗时操作、释放锁来保证线程安全。
    VisitEntity 线程类:
python 复制代码
class VisitEntity(threading.Thread):
    my_bus = ""
    name = ""

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def run(self):
        self.my_bus = Bus()
        self.my_bus.sendData(self.name)
  • VisitEntity 继承自 threading.Thread ,重写了 run 方法。在 run 方法中,它获取 Bus 类的单例实例,并调用其 sendData 方法发送数据,模拟多线程访问单例对象的场景。
    主程序部分:
python 复制代码
if __name__ == "__main__":
    for i in range(3):
        print("Entity %d begin to run..." % i)
        my_entity = VisitEntity()
        my_entity.setName("Entity_"+str(i))
        my_entity.start()
  • 在主程序中,创建了3个 VisitEntity 线程,为每个线程设置名字后启动它们,观察多线程环境下单例对象的运行情况。

原理

  • 单例模式的核心目标:确保一个类只有一个实例,并提供一个全局访问点。在这段代码里,利用 new 方法的特性,类第一次实例化时创建对象,后续实例化请求都返回这个已创建好的对象,以此保证整个程序生命周期内特定类的实例唯一性。
  • 线程安全性:由于多线程环境下,多个线程可能同时尝试创建实例,代码引入了线程锁( RLock )。在 Bus 类的 sendData 方法中,当线程访问共享资源(这里模拟发送数据的操作)时,先获取锁,操作完成后释放锁,防止数据竞争和不一致问题,保证单例模式在并发场景下正常工作。运行这段代码,会发现虽然有多个线程尝试访问 Bus 实例,但它们操作的是同一个实例,并且按顺序依次执行 sendData 方法。
相关推荐
明洞日记27 分钟前
【设计模式手册013】命令模式 - 请求封装的优雅之道
java·设计模式·命令模式
ada0_ada11 小时前
行为型模式:②命令模式(Command Pattern)
设计模式
o0向阳而生0o2 小时前
113、23种设计模式之中介者模式(21/23)
设计模式·中介者模式
心语星光2 小时前
23种经典设计模式
设计模式
Salt_07282 小时前
DAY 19 数组的常见操作和形状
人工智能·python·机器学习
无心水2 小时前
【Python实战进阶】2、Jupyter Notebook终极指南:为什么说不会Jupyter就等于不会Python?
python·jupyter·信息可视化·binder·google colab·python实战进阶·python工程化实战进阶
上班日常摸鱼3 小时前
Shell脚本基础教程:变量、条件判断、循环、函数实战(附案例)
python
无心水4 小时前
【Python实战进阶】5、Python字符串终极指南:从基础到高性能处理的完整秘籍
开发语言·网络·python·字符串·unicode·python实战进阶·python工业化实战进阶
2301_807583234 小时前
了解python,并编写第一个程序,常见的bug
linux·python
小白学大数据4 小时前
构建混合爬虫:何时使用Requests,何时切换至Selenium处理请求头?
爬虫·python·selenium·测试工具