Day 68:【99天精通Python】设计模式 (Design Patterns) 下篇 - 观察者与策略

Day 68:【99天精通Python】设计模式 (Design Patterns) 下篇 - 观察者与策略

前言

欢迎来到第68天!

在昨天的课程中,我们学习了如何优雅地创建对象(单例、工厂)。今天,我们来关注对象之间的交互

  • 观察者模式 (Observer):当一个对象状态改变时,自动通知所有依赖它的对象。(例如:UP主发布视频,粉丝收到推送)。
  • 策略模式 (Strategy):定义一系列算法,让它们可以互换。(例如:地图导航可以选择"最快"、“最短”、"不走高速"等不同策略)。

本节内容:

  • 观察者模式:发布-订阅机制
  • 策略模式:算法的封装与替换
  • Python 内置的functools.partial应用
  • 实战练习:电商促销系统

一、观察者模式 (Observer)

核心思想:一对多依赖。一个主题 (Subject),多个观察者 (Observer)。

1.1 经典实现

# 主题 (被观察者)classNewsChannel:def__init__(self):self._subscribers=[]# 订阅者列表defattach(self,observer):self._subscribers.append(observer)defdetach(self,observer):self._subscribers.remove(observer)defnotify(self,news):forsubinself._subscribers:sub.update(news)# 观察者 (接口)classSubscriber:defupdate(self,news):raiseNotImplementedError# 具体观察者classUser(Subscriber):def__init__(self,name):self.name=namedefupdate(self,news):print(f"{self.name}收到新闻:{news}")classSMSCenter(Subscriber):defupdate(self,news):print(f"[短信中心] 正在发送短信:{news}")# 使用channel=NewsChannel()user1=User("Alice")user2=User("Bob")sms=SMSCenter()channel.attach(user1)channel.attach(user2)channel.attach(sms)channel.notify("Python 3.14 发布啦!")# 输出:# Alice 收到新闻: ...# Bob 收到新闻: ...# [短信中心] ...

1.2 Pythonic 实现:信号机制

在 Django 或 PyQt 中,常用信号 (Signal)来实现观察者模式。我们可以写一个简单的 Signal 类。

classSignal:def__init__(self):self._handlers=[]defconnect(self,handler):self._handlers.append(handler)defemit(self,*args,**kwargs):forhandlerinself._handlers:handler(*args,**kwargs)# 使用video_uploaded=Signal()defnotify_fans(title):print(f"通知粉丝: 新视频《{title}》上线了")defupdate_db(title):print(f"数据库记录: 视频《{title}》已入库")video_uploaded.connect(notify_fans)video_uploaded.connect(update_db)video_uploaded.emit("设计模式详解")

二、策略模式 (Strategy)

核心思想:把算法封装成类(或函数),让它们可以互相替换。

场景:商场打折。

  • 策略 A:打八折。
  • 策略 B:满 100 减 20。
  • 策略 C:VIP 半价。

2.1 传统实现 (面向对象)

fromabcimportABC,abstractmethod# 策略接口classDiscountStrategy(ABC):@abstractmethoddefcalculate(self,price):pass# 具体策略classNormalStrategy(DiscountStrategy):defcalculate(self,price):returnpriceclassTenPercentOffStrategy(DiscountStrategy):defcalculate(self,price):returnprice*0.9classOver100Minus20Strategy(DiscountStrategy):defcalculate(self,price):ifprice>=100:returnprice-20returnprice# 上下文 (使用策略的类)classOrder:def__init__(self,price,strategy:DiscountStrategy):self.price=price self.strategy=strategydeffinal_price(self):returnself.strategy.calculate(self.price)# 使用order=Order(100,TenPercentOffStrategy())print(f"折后价:{order.final_price()}")# 90.0

2.2 Pythonic 实现:函数即对象

Python 中函数是一等公民,没必要非得定义类。

deften_percent_off(price):returnprice*0.9defover_100_minus_20(price):returnprice-20ifprice>=100elsepriceclassOrder:def__init__(self,price,strategy_func):self.price=price self.func=strategy_funcdeffinal_price(self):returnself.func(self.price)# 使用order=Order(200,over_100_minus_20)print(f"折后价:{order.final_price()}")# 180

2.3 进阶:使用 partial 固定参数

如果策略函数需要额外的参数(比如打 n 折),可以使用functools.partial

fromfunctoolsimportpartialdefdiscount(price,rate):returnprice*rate# 创建一个 "打8折" 的策略strategy_80=partial(discount,rate=0.8)order=Order(100,strategy_80)print(order.final_price())# 80.0

三、实战练习:电商促销系统

结合观察者和策略模式。

  1. 观察者:订单支付成功后,通知库存系统(扣减)、通知物流系统(发货)、通知积分系统(加分)。
  2. 策略:根据用户等级(普通、VIP)自动选择不同的计算价格策略。
# --- 1. 观察者 (Event Bus) ---classEventBus:def__init__(self):self.listeners={}defsubscribe(self,event_type,listener):ifevent_typenotinself.listeners:self.listeners[event_type]=[]self.listeners[event_type].append(listener)defpublish(self,event_type,data):ifevent_typeinself.listeners:forlistenerinself.listeners[event_type]:listener(data)bus=EventBus()# --- 2. 策略 (Pricing) ---defvip_pricing(price):returnprice*0.8defnormal_pricing(price):returnprice# --- 3. 业务逻辑 ---defon_paid(order):print(f"[库存] 扣减商品:{order['item']}")defon_paid_notify(order):print(f"[短信] 您的订单{order['id']}已支付")# 注册监听bus.subscribe("order_paid",on_paid)bus.subscribe("order_paid",on_paid_notify)classOrderSystem:defcreate_order(self,user_type,item,price):# 策略选择strategy=vip_pricingifuser_type=="vip"elsenormal_pricing final=strategy(price)order={"id":1001,"item":item,"total":final}print(f"订单创建,应付:{final}")# 模拟支付print("支付成功...")# 触发观察者bus.publish("order_paid",order)# 运行sys=OrderSystem()sys.create_order("vip","Python Book",100)

四、常见问题

Q1:什么时候用继承,什么时候用策略模式?

  • 继承:是静态的。一旦定义了class VIPOrder(Order),行为就固定了。
  • 策略模式:是动态的。可以在运行时切换策略order.strategy = new_strategy
    原则:多用组合(策略),少用继承。

Q2:Python 的装饰器算不算观察者模式?

不算。装饰器是结构型模式(Wrapper),用于增强功能。观察者是行为型模式,用于解耦通知。


五、小结

设计模式 (行为)

观察者 Observer

策略 Strategy

发布-订阅 (Pub-Sub)

解耦核心逻辑与副作用

应用: 信号、事件驱动

封装算法

运行时切换

消除 if-else

应用: 支付方式、折扣

关键要点

  1. 观察者模式:一方有难,八方支援(一方变动,通知八方)。
  2. 策略模式:条条大路通罗马(多种算法,随意切换)。
  3. Python 的函数式特性(函数作为参数)让这两个模式实现起来非常简洁。

六、课后作业

  1. 股票监控器:使用观察者模式。当股票价格变动时,通知:控制台打印器、邮件发送器(Day 43)、日志记录器(Day 33)。
  2. 排序策略:编写一个Sorter类,可以接受不同的排序策略(如bubble_sort,quick_sort),对列表进行排序。
  3. 游戏角色:设计一个游戏角色类,使用策略模式实现更换武器(WeaponStrategy)。比如:use_weapon()在装备"剑"时是近战伤害,装备"弓"时是远程伤害。

下节预告

Day 69:C/C++ 扩展 (CTypes/Cython)- Python 跑得慢怎么办?设计模式救不了你,但 C 语言可以!明天我们学习如何用 Python 调用 C 代码,获得百倍性能提升。


系列导航

  • 上一篇:Day 67 - 设计模式上
  • 下一篇:Day 69 - C/C++扩展(待更新)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1170974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Z-Image-ComfyUI工作流分享:导出导入JSON文件的操作步骤

Z-Image-ComfyUI工作流分享:导出导入JSON文件的操作步骤 1. 引言 1.1 业务场景描述 在当前AIGC(人工智能生成内容)快速发展的背景下,图像生成模型的应用日益广泛。Z-Image-ComfyUI作为基于阿里最新开源文生图大模型Z-Image的可…

Sambert性能优化技巧:让语音合成速度提升50%

Sambert性能优化技巧:让语音合成速度提升50% 1. 引言:多情感语音合成的性能挑战 随着AI语音技术在虚拟主播、智能客服、有声读物等场景中的广泛应用,用户对高质量、低延迟的语音合成服务提出了更高要求。Sambert-HifiGAN作为当前主流的中文…

Python3.8图像处理:云端OpenCV预装,免去编译痛苦

Python3.8图像处理:云端OpenCV预装,免去编译痛苦 你是不是也遇到过这种情况?作为一名设计师,想用Python来批量处理图片、自动裁剪构图、提取配色方案,或者给设计稿加水印。兴致勃勃地打开教程,照着代码敲完…

Day 69:【99天精通Python】C/C++ 扩展 (CTypes/Cython) - 给 Python 装上喷气引擎

Day 69:【99天精通Python】C/C 扩展 (CTypes/Cython) - 给 Python 装上喷气引擎 前言 欢迎来到第69天! Python 的优点是开发效率极高,但缺点也很明显:运行速度慢(相比 C/C)。 在绝大多数场景下,…

单目深度估计实战:MiDaS模型部署与优化

单目深度估计实战:MiDaS模型部署与优化 1. 引言 1.1 技术背景 在计算机视觉领域,从单张二维图像中恢复三维空间结构一直是极具挑战性的任务。传统方法依赖多视角几何或激光雷达等硬件设备,成本高且部署复杂。随着深度学习的发展&#xff0…

效果展示:通义千问2.5-7B-Instruct打造的智能写作助手案例

效果展示:通义千问2.5-7B-Instruct打造的智能写作助手案例 1. 引言:为何选择通义千问2.5-7B-Instruct构建智能写作助手 在当前大模型快速发展的背景下,如何选择一个性能强、响应快、部署灵活且支持商用的开源模型,成为构建垂直领…

树莓派换源零基础指南:网络环境要求

树莓派换源实战指南:从卡顿到飞速的秘诀你有没有遇到过这种情况:刚入手树莓派,兴致勃勃地打开终端准备安装Python库或者升级系统,结果一条sudo apt update执行下去,半天不动,进度条像被冻住了一样&#xff…

CC2530零基础入门:串口下载与调试方式详解

CC2530入门实战:串口下载与调试全解析 你是不是也遇到过这种情况——手里的CC2530开发板接上电脑,打开烧录工具,结果提示“无法连接芯片”?反复检查线序、波特率、跳线,就是搞不定。别急,这几乎是每个ZigB…

IndexTTS2效果优化:语调、停顿、重音调节实战技巧

IndexTTS2效果优化:语调、停顿、重音调节实战技巧 1. 引言:提升语音自然度的关键挑战 随着AI语音合成技术的快速发展,用户对TTS(Text-to-Speech)系统的自然度和表现力提出了更高要求。尽管IndexTTS2在V23版本中显著增…

A.每日一题——2975. 移除栅栏得到的正方形田地的最大面积

题目链接:2975. 移除栅栏得到的正方形田地的最大面积(中等) 算法原理: 解法:暴力枚举 622ms击败78.57% 时间复杂度O(N) 此题跟上一题 A.每日一题——2943. 最大化网格图中正方形空洞的面积 的不同点👇 空洞…

从语料到模型应用|StructBERT中文情感分析镜像全链路实践

从语料到模型应用|StructBERT中文情感分析镜像全链路实践 1. 引言:中文情感分析的现实挑战与技术选型 1.1 情感分析在实际业务中的价值 在当前以用户为中心的产品运营体系中,中文情感分析已成为企业洞察用户反馈、优化服务体验的核心能力。…

D.二分查找-进阶——658. 找到 K 个最接近的元素

题目链接:658. 找到 K 个最接近的元素(中等) 算法原理: 解法一:排序 19ms击败13.08% 时间复杂度O(NlogN) 这个解法其实挺暴力的,直接用把arr全扔链表里,然后按照题目要求把链表排序,…

Java SpringBoot+Vue3+MyBatis 抗疫物资管理系统系统源码|前后端分离+MySQL数据库

💡实话实说:有自己的项目库存,不需要找别人拿货再加价,所以能给到超低价格。摘要 新冠疫情爆发以来,全球范围内对防疫物资的需求急剧增加,如何高效、精准地管理抗疫物资成为各级政府和医疗机构面临的重大挑…

【2025最新】基于SpringBoot+Vue的学生网上请假系统管理系统源码+MyBatis+MySQL

💡实话实说:有自己的项目库存,不需要找别人拿货再加价,所以能给到超低价格。摘要 随着信息化技术的快速发展,传统纸质请假流程已无法满足现代高校管理的需求。学生请假流程繁琐、审批效率低下、数据统计困难等问题日益…

gpt-oss-20b-WEBUI实战:云端10分钟部署,2块钱玩一下午

gpt-oss-20b-WEBUI实战:云端10分钟部署,2块钱玩一下午 你是不是也遇到过这样的场景?团队里有人用AI写产品文案,几分钟就输出一整套卖点提炼、用户话术和推广标题,效率高得离谱。而你还卡在“这个功能怎么描述更吸引人…

BGE-M3一键启动:语义搜索实战指南(附避坑技巧)

BGE-M3一键启动:语义搜索实战指南(附避坑技巧) 1. 引言 1.1 业务场景与技术背景 在当前信息爆炸的时代,高效、精准的语义搜索已成为智能应用的核心能力之一。无论是知识库问答系统、推荐引擎还是文档检索平台,背后都…

DeepSeek-R1-Distill-Qwen-1.5B高效运维:日志监控与性能分析实战

DeepSeek-R1-Distill-Qwen-1.5B高效运维:日志监控与性能分析实战 1. 引言:轻量级大模型的运维挑战与机遇 随着边缘计算和本地化AI部署需求的增长,轻量级大模型正成为开发者和运维工程师关注的焦点。DeepSeek-R1-Distill-Qwen-1.5B 作为一款…

如何高效批量抠图?试试CV-UNet大模型镜像,本地部署秒级出图

如何高效批量抠图?试试CV-UNet大模型镜像,本地部署秒级出图 1. 背景与需求:AI抠图的效率革命 在电商、广告设计、内容创作等领域,图像背景移除是一项高频且耗时的任务。传统依赖Photoshop等专业工具的手动抠图方式,不…

Qwen3-VL-WEB保姆级教程:多语言文本识别实战应用

Qwen3-VL-WEB保姆级教程:多语言文本识别实战应用 1. 引言 1.1 业务场景描述 在当今全球化背景下,跨语言信息处理已成为企业数字化转型中的关键需求。无论是跨境电商的商品标签识别、国际文档的自动化归档,还是多语种用户界面的内容提取&am…

Qwen3-Embedding-0.6B最佳实践:云端部署省时省力

Qwen3-Embedding-0.6B最佳实践:云端部署省时省力 你是否也遇到过这样的科研困境?实验室GPU资源紧张,排队等上好几天才能跑一次任务;项目进度卡在数据预处理环节,团队协作效率低下。尤其是在做社会舆情分析这类需要批量…