当前位置: 首页 > news >正文

基于Python学习《Head First设计模式》第二章 观察者模式

观察者模式

定义

在这里插入图片描述

类图

在这里插入图片描述

应用项目:气象站

要求

在这里插入图片描述
在这里插入图片描述

实现类图

在这里插入图片描述

实现方式1-更新所有观察者的所有数据

搭建观察者模式框架

在这里插入图片描述


class Observer:"""观察者"""@abstractmethoddef update(self,temp, humidity, pressure):"""由主题调用更新"""passclass Subject:"""主题"""@abstractmethoddef register_observer(self, observer: Observer):"""注册"""pass@abstractmethoddef remove_observer(self, observer: Observer):"""移除"""pass@abstractmethoddef notify_observers(self):"""通知所有观察者"""passclass DisplayElement:def __init__(self):pass@abstractmethoddef display(self):"""显示"""pass

实现WeatherData

在这里插入图片描述

class WeatherData(Subject):def __init__(self):self._observers: list[Observer] = []self._temp: Optional[float] = Noneself._pressure: Optional[float] = Noneself._humidity: Optional[float] = Nonedef register_observer(self, observer: Observer):self._observers.append(observer)def remove_observer(self, observer: Observer):self._observers.remove(observer)def notify_observers(self):for obs in self._observers:obs.update(self._temp, self._humidity, self._pressure)def measurements_changed(self):self.notify_observers()def set_measurements(self, temp: float, humidity: float, pressure: float):self._temp = tempself._humidity = humidityself._pressure = pressureself.measurements_changed()

实现布告板

在这里插入图片描述

class CurrentConditionsDispaly(Observer, DisplayElement):def __init__(self):self._weather_data = WeatherData()self._weather_data.register_observer(self)self._temp: Optional[float] = Noneself._pressure: Optional[float] = Noneself._humidity: Optional[float] = Nonedef update(self, temp, humidity, pressure):self._temp = tempself._humidity = humidityself._pressure = pressureself.display()def display(self):print(id(self))  # 打印当前示例id,用于区分print(f"温度:{self._temp}"f"湿度:{self._humidity}"f"气压:{self._pressure}")

测试&运行

在这里插入图片描述

if __name__ == '__main__':weather = WeatherData()display = CurrentConditionsDispaly(weather)weather.set_measurements(80, 80, 2.34)display2 = CurrentConditionsDispaly(weather)weather.set_measurements(90, 70.5, 5)

完整代码


from abc import abstractmethod
from typing import Optionalclass Observer:"""观察者"""@abstractmethoddef update(self, temp, humidity, pressure):"""由主题调用更新"""passclass Subject:"""主题"""@abstractmethoddef register_observer(self, observer: Observer):"""注册"""pass@abstractmethoddef notify_observers(self):"""通知所有观察者"""pass@abstractmethoddef remove_observer(self, observer: Observer):"""移除"""passclass DisplayElement:@abstractmethoddef display(self):"""显示"""passclass WeatherData(Subject):def __init__(self):self._observers: list[Observer] = []self._temp: Optional[float] = Noneself._pressure: Optional[float] = Noneself._humidity: Optional[float] = Nonedef register_observer(self, observer: Observer):self._observers.append(observer)def remove_observer(self, observer: Observer):self._observers.remove(observer)def notify_observers(self):for obs in self._observers:obs.update(self._temp, self._humidity, self._pressure)def measurements_changed(self):self.notify_observers()def set_measurements(self, temp: float, humidity: float, pressure: float):self._temp = tempself._humidity = humidityself._pressure = pressureself.measurements_changed()class CurrentConditionsDispaly(Observer, DisplayElement):def __init__(self, weather_data: WeatherData):self._weather_data = weather_dataself._weather_data.register_observer(self)self._temp: Optional[float] = Noneself._pressure: Optional[float] = Noneself._humidity: Optional[float] = Nonedef update(self, temp, humidity, pressure):self._temp = tempself._humidity = humidityself._pressure = pressureself.display()def display(self):print(id(self))print(f"温度:{self._temp}\n"f"湿度:{self._humidity}\n"f"气压:{self._pressure}\n")if __name__ == '__main__':weather = WeatherData()display = CurrentConditionsDispaly(weather)weather.set_measurements(80, 80, 2.34)display2 = CurrentConditionsDispaly(weather)weather.set_measurements(90, 70.5, 5)"""运行结果:
4481847152
温度:80
湿度:80
气压:2.344481847152
温度:90
湿度:70.5
气压:54481845424
温度:90
湿度:70.5
气压:5
"""

实现方式2-通知观察者自行拉取数据更新

类图

在这里插入图片描述

代码实现

在这里插入图片描述


from abc import abstractmethod, ABC
from typing import Optional, Unionclass Observer(ABC):"""观察者"""@abstractmethoddef update(self, observerable, arg):"""由主题调用更新"""passclass Observerable:"""可观察者"""_observers = []changed = Falsedef register_observer(self, observer: Observer):self._observers.append(observer)def remove_observer(self, observer: Observer):self._observers.remove(observer)def notify_observers(self, arg=None):if self.changed:for obs in self._observers:obs.update(self, arg)else:self.changed = Falsedef set_changed(self):self.changed = Trueclass DisplayElement:@abstractmethoddef display(self):"""显示"""passclass WeatherData(Observerable):_temp: float  # python新版本可不指定默认值_humidity: float_pressure: floatdef measurements_changed(self):self.set_changed()self.notify_observers()def get_temperature(self) -> float:return self._tempdef get_humility(self) -> float:return self._humiditydef get_pressure(self) -> float:return self._pressuredef set_measurements(self, temp: float, humidity: float, pressure: float):self._temp = tempself._humidity = humidityself._pressure = pressureself.measurements_changed()class CurrentConditionsDispaly(Observer, DisplayElement):_temp: float  # python新版本可不指定默认值_humidity: Optional[float]  # 值类型可以为float和None时,可以用 Optional[float] 相当于 Union[float, None]_pressure: Union[float, None]def __init__(self, observerable: Observerable):self._observerable = observerableobserverable.register_observer(self)def update(self, observerable, arg):if isinstance(observerable, WeatherData):self._temp = observerable.get_temperature()self._pressure = observerable.get_pressure()self._humidity = observerable.get_humility()self.display()def display(self):print(id(self))print(f"温度:{self._temp}\n"f"湿度:{self._humidity}\n"f"气压:{self._pressure}\n")if __name__ == '__main__':weather = WeatherData()display = CurrentConditionsDispaly(weather)weather.set_measurements(80, 80, 2.34)display2 = CurrentConditionsDispaly(weather)weather.set_measurements(90, 70.5, 5)

总结

在这里插入图片描述

http://www.xdnf.cn/news/753103.html

相关文章:

  • 基于 Flickr30k-Entities 数据集 的 Phrase Localization
  • 动态规划第二弹:路径类问题(不同路径,珠宝的最高价值,地下城游戏)
  • rtpmixsound:实现音频混音攻击!全参数详细教程!Kali Linux教程!
  • 五、单元测试-概述入门
  • SQL进阶之旅 Day 10:执行计划解读与优化
  • FFmpeg学习笔记
  • SDL_CreateRendererWithProperties报错Parameter ‘window‘ is invalid
  • Maven概述,搭建,使用
  • leetcode-hot-100 (矩阵)
  • 设计模式——组合设计模式(结构型)
  • Android第十一次面试补充篇
  • 读《Go语言圣经记录》(二):深入理解Go语言的程序结构
  • NodeJS全栈开发面试题讲解——P10微服务架构(Node.js + 多服务协作)
  • VMware Tools 手动编译安装版
  • qwen-0.5b小模型的用处和显存要求
  • Unity Mono与IL2CPP比较
  • 大模型备案中语料安全详细说明
  • 开源库免费API服务平台 ALLBEAPI
  • unix/linux source 命令,其内部结构机制
  • unix/linux source 命令,其高级使用
  • 通义开源视觉感知多模态 RAG 推理框架 VRAG-RL:开启多模态推理新时代
  • 【前端】html2pdf实现用前端下载pdf
  • Python Django完整教程与代码示例
  • Vue3 + Element Plus 防止按钮重复点击的解决方案
  • LabVIEW多按键自动化检测系统
  • 03 APP 自动化-定位元素工具元素定位
  • LabVIEW双光子显微镜开发
  • lidar和imu的标定(四)小结
  • Rust 学习笔记:自定义构建和发布配置
  • Linux 内核中 skb_dst_drop 的深入解析:路由缓存管理与版本实现差异