设计模式 19 观察者模式

设计模式 19

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • 设计模式 19
    • 观察者模式(Observer Pattern)
      • 1 定义
      • 2 结构
      • 3 示例代码
      • 4 特点
      • 5 适用场景
      • 6 总结

观察者模式(Observer Pattern)

1 定义

观察者模式的核心思想是当一个对象(被观察者)的状态改变时,所有依赖于它的对象(观察者)都会被通知并更新。这样一来,观察者模式实现了对象之间的松散耦合,使得一个对象的变化可以自动地传播到相关的对象。

2 结构

观察者模式包含以下角色:

  • 主题(Subject): 被观察的对象,维护着一组观察者对象的引用,提供注册、移除观察者的接口,并在状态发生变化时通知所有观察者。
  • 观察者(Observer): 定义一个更新接口,当收到通知时进行相应的更新操作。
  • 具体主题(ConcreteSubject): 具体的被观察对象,通常包含状态,当状态发生变化时,通知所有已注册的观察者。
  • 具体观察者(ConcreteObserver): 实现观察者接口,负责在状态变化时更新自身。

UML 类图

+---------------------------+         +-------------------+
|     Subject               | <------ |     Observer      |
+---------------------------+         +-------------------+
| + Attach(obs: Observer)   |         | + Update(): void  |
| + Detach(obs: Observer)   |         +-------------------+
| + Notify(): void          |               ^
+---------------------------+               |^                                   ||                                   |
+-----------------------+             +-------------------+
| ConcreteSubject       |             | ConcreteObserver  |
+-----------------------+             +-------------------+
| - state: State        |             | - state: State    |
| + GetState(): State   |             | + Update(): void  |
| + SetState(State)     |             +-------------------+
+-----------------------+

3 示例代码

假设我们要实现一个天气站系统,天气站会记录当前的天气信息,并通知注册的显示设备(如手机应用、网站等)进行更新。

观察者接口

// 观察者接口
public interface IObserver
{void Update(string temperature, string humidity, string pressure);
}

主题接口

// 主题接口
public interface ISubject
{void RegisterObserver(IObserver observer);void RemoveObserver(IObserver observer);void NotifyObservers();
}

具体主题

// 具体主题
public class WeatherStation : ISubject
{private List<IObserver> _observers;private string _temperature;private string _humidity;private string _pressure;public WeatherStation(){_observers = new List<IObserver>();}public void RegisterObserver(IObserver observer){_observers.Add(observer);}public void RemoveObserver(IObserver observer){_observers.Remove(observer);}public void NotifyObservers(){foreach (var observer in _observers){observer.Update(_temperature, _humidity, _pressure);}}public void SetMeasurements(string temperature, string humidity, string pressure){_temperature = temperature;_humidity = humidity;_pressure = pressure;NotifyObservers();}
}

具体观察者

// 具体观察者
public class PhoneDisplay : IObserver
{private string _temperature;private string _humidity;private string _pressure;public void Update(string temperature, string humidity, string pressure){_temperature = temperature;_humidity = humidity;_pressure = pressure;Display();}public void Display(){Console.WriteLine($"Phone Display -> Temperature: {_temperature}, Humidity: {_humidity}, Pressure: {_pressure}");}
}public class WebDisplay : IObserver
{private string _temperature;private string _humidity;private string _pressure;public void Update(string temperature, string humidity, string pressure){_temperature = temperature;_humidity = humidity;_pressure = pressure;Display();}public void Display(){Console.WriteLine($"Web Display -> Temperature: {_temperature}, Humidity: {_humidity}, Pressure: {_pressure}");}
}

客户端代码

class Program
{static void Main(string[] args){WeatherStation weatherStation = new WeatherStation();IObserver phoneDisplay = new PhoneDisplay();IObserver webDisplay = new WebDisplay();weatherStation.RegisterObserver(phoneDisplay);weatherStation.RegisterObserver(webDisplay);weatherStation.SetMeasurements("30°C", "65%", "1013 hPa");weatherStation.RemoveObserver(phoneDisplay);weatherStation.SetMeasurements("28°C", "70%", "1012 hPa");}
}

运行结果

Phone Display -> Temperature: 30°C, Humidity: 65%, Pressure: 1013 hPa
Web Display -> Temperature: 30°C, Humidity: 65%, Pressure: 1013 hPa
Web Display -> Temperature: 28°C, Humidity: 70%, Pressure: 1012 hPa

在这个例子中,WeatherStation 是具体的主题,当天气数据发生变化时,它通知所有注册的观察者(如 PhoneDisplayWebDisplay)进行更新并显示新的数据。

4 特点

  • 优点:

    • 松散耦合: 观察者和主题之间是松散耦合的,观察者可以独立于主题的变化而变化,增加了系统的灵活性。

    • 动态更新: 观察者模式使得对象之间的通信更加灵活,可以动态添加或删除观察者,实时更新数据。

    • 符合开放-封闭原则: 可以在不修改现有代码的情况下,增加新的观察者。

  • 缺点:

    • 通知开销: 如果有大量的观察者,通知所有观察者可能会引起开销,影响性能。

    • 可能出现循环依赖: 如果观察者之间也相互依赖,可能会导致循环依赖问题,影响系统的稳定性。

5 适用场景

  • 事件处理系统: 当需要对某个事件发生时,触发多个对象的响应时,观察者模式非常适用。
  • 数据模型与视图同步: 在模型-视图架构中,当模型的数据变化时,需要通知视图更新显示,可以使用观察者模式。
  • 广播通信: 当一个对象的状态改变需要通知多个对象时,可以使用观察者模式。

6 总结

观察者模式通过定义一对多的依赖关系,实现了对象间的松散耦合和动态通信。它允许对象自动通知相关的依赖对象并更新状态,非常适合用于事件驱动的系统和需要动态更新的场景。尽管可能会带来一定的通知开销和复杂性管理,但它依然是实现对象间动态通信的强大工具。

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

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

相关文章

十二、建立自已的北斗卫星实时定位基站

一、背景 连续运行卫星定位服务系统(Continuous Operational Reference System,简称CORS系统)是现代北斗/GNSS的发展热点之一。CORS系统将网络化概念引入到了大地测量应用中,该系统的建立不仅为测绘行业带来深刻的变革,而且也将为现代网络社会中的空间信息服务带来新的思维…

基于单片机的水箱水质监测系统设计

本设计基于STM32F103C8T6为核心控制器设计了水质监测系统&#xff0c;选用DS18B20温度传感器对水箱水体温度进行采集&#xff1b;E-201-C PH传感器获取水体PH值&#xff1b;选用TS-300B浊度传感器检测水体浊度&#xff1b;采用YW01液位传感器获取水位&#xff0c;当检测水位低于…

宽带和带宽分不清楚

如何理解带宽 我们平时经常听到的带宽其实是宽带&#xff0c;举个栗子&#xff1a;我家用的是xx运营商提供的&#xff0c;号称1000M宽带&#xff0c;这其实指是的网络数据传输的速率是&#xff1a;1000Mbs&#xff08;即125MBps&#xff09;。 那么既然有宽带&#xff0c;就有…

【LVGL- 组 lv_group_t】

lv_group_t ■ group■ 组api■ lv_group_create后后面的控件自动添加到group ■ group if (code LV_EVENT_SCREEN_LOADED) //一般放在loaded 事件中添加到lv_group_set_default(key_group); lv_indev_set_group(indev_keypad, key_group); //和输入设备关联。 }■ 组api…

MCU官方IDE软件安装及学习教程集合 — STM32CubeIDE(STM32)

简介 各MCU厂商为保证产品的市场地位以及用户体验&#xff0c;不断的完善自己的产品配套&#xff0c;搭建自己的开发生态&#xff0c;像国外ST公司&#xff0c;国内的GD&#xff08;兆易创新&#xff09;&#xff0c;AT&#xff08;雅特力&#xff09;等等。目前就开发生态而言…

09.定时器02

#include "reg52.h"sbit led P3^6;void delay10ms() { //1. 配置定时器0工作模式位16位计时TMOD 0x01;//2. 给初值&#xff0c;定一个10ms出来TL00x00;TH00xDC;//3. 开始计时TR0 1;TF0 0; } void main() {int cnt 0;led 1;while(1){if(TF0 1)//当爆表的时候&a…

【Qt】QLCDNumber | QProgressBar | QCalendarWidget

文章目录 QLCDNumber —— 显示数字QLCDNumber 的属性QLCDNumber 的使用 QProgressBar —— 进度条QProgressBar 的属性创建一个进度条修改为 红色的进度条 QCalendarWidget —— 日历QCalendarWidget 的属性QCalendarWidget 的使用 QLCDNumber —— 显示数字 QLCDNumber 的属…

UE4_后期处理_后期处理材质及后期处理体积一

后期处理效果 在渲染之前应用于整个渲染场景的效果。 后期处理效果&#xff08;Post-processing effect&#xff09;使美术师和设计师能够对影响颜色、色调映射、光照的属性和功能进行组合选择&#xff0c;从而定义场景的整体外观。要访问这些功能&#xff0c;可以将一种称为…

使用docker调试odoo

使用 Visual Studio Code (VSCode) 的 Dev Containers 进行 Odoo 开发和调试是一个高效的方法&#xff0c;尤其是当你希望在一个清洁且一致的开发环境中工作时。以下是设置和配置 Dev Container 以在 Docker 环境中单步调试 Odoo 系统的步骤&#xff1a; ### 步骤 1: 准备 Doc…

多角度解读WMS:探寻仓库管理系统的核心功能

多角度解读 WMS 仓库管理系统 1. 概述 WMS 在数字化工厂中具有举足轻重的地位&#xff0c;它不仅提高了仓储管理的效率与准确性&#xff0c;还能优化整个供应链的管理&#xff0c;支持灵活生产模式&#xff0c;并提供决策支持的关键数据。通过现代前后端技术的架构设计&#xf…

【Spring Boot 3】自定义拦截器

【Spring Boot 3】自定义拦截器 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或…

Prometheus_0基础_学习笔记

一、基本概念 Prometheus是由golang语言开发的一套开源的监控、报警、时间序列数据库的组合&#xff0c;是一款基于时序数据库的开源监控告警系统。 时间序列数据库&#xff1a;时间序列数据库&#xff08;Time Serires Database , TSDB&#xff09;不同于传统的关系型数据库。…

idea如何高亮、标记代码颜色的2种方式

zihao 第一种高亮方式 ctrlf 双击选择执行快捷键&#xff0c;所有被搜索的单词都会被搜索且高亮 第二种高亮方式 安装grep console 日志管理插件 ctrlaltf3 双击选择执行快捷键&#xff0c;所有被标记一个颜色高亮

银行卡二三四要素验证-银行卡二三四要素验证接口-银行卡二三四要素验证api

1、接口介绍 银行卡二三四要素验证接口是一种用于验证用户银行卡信息真实性和有效性的技术接口。这种接口在金融、电商等领域有着广泛的应用&#xff0c;旨在确保交易的安全性和合规性。 2、接口地址 全面覆盖&#xff0c;支持所有带银联标识的银行卡; 高准确性-验证结果实时返…

Kubernetes Secret的三种使用方式

Kubernetes Secret的三种使用方式 1、方式一:通过Service Account自动使用2、方式二:挂载Secret到Pod3、方式三:在Docker镜像下载时使用💖The Begin💖点点关注,收藏不迷路💖 在Kubernetes中,Secret是管理敏感信息的利器。创建Secret后,我们可以通过以下三种简洁的方…

RabbitMQ 入门:基本概念、特性及简单示例

什么是 RabbitMQ&#xff1f; RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。它支持多种消息协议&#xff0c;包括 AMQP 0-9-1&#xff0c;并提供了可靠性、灵活的路由、消息持久性等功能。RabbitMQ 是易于使用的&#xff0c;支持多种编程语言&a…

科技型中小企业怎么做

在当今快速发展的科技时代&#xff0c;科技型中小企业扮演着越来越重要的角色。这些企业不仅推动了技术创新&#xff0c;还为经济增长和社会进步做出了巨大贡献。那么&#xff0c;科技型中小企业应如何制定并执行其发展战略呢&#xff1f; 1. 明确定位与战略规划 对于任何企业…

云服务器+docker:还在为项目上线苦恼?一文包你解决(保姆级教程,图文并茂,万字起步!!!)

目录 Blue留言机&#xff1a; 学习视频以及参考资料 &#xff1a; 1、学习之前的必备操作&#xff1a; 第一步&#xff1a;购买服务器 选择一台免费的云服务器&#xff08;包白嫖的&#xff09; 配置服务器的一点说明&#xff1a; 查看自己是否购买成功&#xff1a; 第…

docker制作达梦数据库驱动的Python镜像记录

docker制作达梦数据库驱动的Python镜像记录 使用Sqlalchemy ORM 操作达梦 提供构建好的docker镜像 docker pull chongjing001/python:3.12 使用虚拟环境(source /venv/bin/activate) 后pip其他库 镜像中安装Python参考上一篇 下载DM8安装包 版本选择 官网 Linux安装包只有 r…

Python基础笔记

一、python基础1.1 基础知识1.1.1 注释 注释&#xff1a;在程序中对程序代码进行解释说明的文字。 作用&#xff1a;注释不是程序&#xff0c;不能被执行&#xff0c;只是对程序代码进行解释说明&#xff0c;让别人可以看懂程序代码的作用&#xff0c;能够大大增强程序的可读性…