设计模式 19 观察者模式

news/2024/9/17 8:06:22/ 标签: 设计模式, 观察者模式

设计模式 19

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

文章目录

观察者模式(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.ppmy.cn/news/1522777.html

相关文章

自动化抢票 12306

自动化抢票 12306 1. 明确需求 明确采集的网站以及数据内容 网址: https://kyfw.12306.cn/otn/leftTicket/init数据: 车次相关信息 2. 抓包分析 通过浏览器开发者工具分析对应的数据位置 打开开发者工具 F12 或鼠标右键点击检查 刷新网页 点击下一页/下滑网页页面/点击搜…

stm32之外部flash下载算法

文章目录 下载算法下载到芯片的核心思想算法程序中擦除操作执行流程擦除操作大致流程&#xff1a;算法程序中编程操作执行流程算法程序中校验操作执行流程 创建MDK下载算法通用流程第1步&#xff0c;使用MDK提供好的程序模板第2步&#xff0c;修改工程名第3步&#xff0c;修改使…

LiveKit的agent介绍

概念 LiveKit核心概念&#xff1a; Room&#xff08;房间&#xff09;Participant&#xff08;参会人&#xff09;Track&#xff08;信息流追踪&#xff09; Agent 架构图 ​ 订阅信息流 ​ agent交互流程 客户端操作 加入房间 房间创建方式 手动 赋予用户创建房间的…

STM32(十二):DMA直接存储器存取

DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预&#xff0c;节省了CPU的资源。&#xff08;运行内存SRAM、程序存储器Flash、寄存器&#xff09; 12个独立可配置的通道&…

SAP自动化操作

业务场景 1、主数据维护&#xff08;物料、成本中心、科目、资产、供应商、客户等等&#xff09; 2、业务单据创建&#xff08;包括内部订单、销售订单&#xff0c;采购订单&#xff0c;生产订单&#xff0c;交货单等等&#xff09; 3、业务单据处理&#xff08;订单评审&…

HTTP 二、进阶

四、安全 1、TLS是什么 &#xff08;1&#xff09;为什么要有HTTPS ​ 简单的回答是“因为 HTTP 不安全”。由于 HTTP 天生“明文”的特点&#xff0c;整个传输过程完全透明&#xff0c;任何人都能够在链路中截获、修改或者伪造请求 / 响应报文&#xff0c;数据不具有可…

【多线程服务器】多线程下网络编程

目录 多线程模型-非阻塞IOone loop per thread one loop per thread 线程池 one loop per thread与线程池结合 目前主流多线程模型 Reactor模式线程池 Proactor模式 Master-Worker模型 多线程编程的实现 线程抢占问题 Happens-Before关系 Linux下多线程编程常用函数 …

keepalived和lvs高可用集群

keepavlied和lvs高可用集群搭建 主备模式&#xff1a; 关闭防火墙和selinux systemctl stop firewalld setenforce 0部署master负载调度服务器 zyj86 安装ipvsadm keepalived yum install -y keepalived ipvsadm修改主节点配置 vim /etc/keepalived/keepalived.conf! Conf…

C语言小游戏--贪吃蛇实现

C语言小游戏--贪吃蛇实现 1.游戏实现背景2.Win32 API介绍2.1什么是Win32 API2.2控制台程序(Console)2.3控制台屏幕的坐标COORD2.4GetStdHandle2.4.1函数语法2.4.2函数的使用 2.5GetConsoleCursorInfo2.5.1函数语法2.5.2函数的使用 2.6CONSOLE_CURSOR_INFO2.6.1结构体结构2.6.2结…

【RabbitMQ】核心概念

界⾯上的导航栏共分6部分, 这6部分分别是什么意思呢, 我们先看看RabbitMQ的工作流程 1. Producer和Consumer Producer:生产者,是RabbitMQ Server的客户端,向RabbitMQ发送消息 Consumer: 消费者,也是RabbitMQ Server的客户端,从RabbitMQ接收消息 Broker:其实就是RabbitMQSer…

UE4_地形_悬崖拉伸的解决

参考教程 【虚幻5】UE5_UE4_解决悬崖地形贴图拉伸_哔哩哔哩_bilibili 纹理处理 | 虚幻引擎 4.27 文档 | Epic Developer Community (epicgames.com) 主要通过蓝图节点解决&#xff1a;WorldAlignedTexture WorldAlignedTexture&#xff08;全局一致纹理&#xff09;函数用于…

js(vue)如何实现页面截图,向后端传递,生成PDF

利用 htmm12canvas 首先引入 npm install express multer # 或者 yarn add express multer 代码如下&#xff1a; <template><!-- <div style"width:100%;height:100%;overflow-y: scroll"><img :src"svg" style"width: 100%;&…

【H2O2|全栈】关于HTML(3)HTML基础(二)

HTML相关知识 目录 HTML相关知识 前言 准备工作 标签的具体分类&#xff08;二&#xff09; 本文中的标签在什么位置使用&#xff1f; 本期前置知识点 超文本 超文本引用和源属性 图片标签 锚链接 iframe 锚点 预告和回顾 后话 前言 本系列博客将分享HTML相关…

SprinBoot+Vue应急信息管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

docker ps -a及docker exec -it ubuntu-01 /bin/bash

docker ps -a 命令 在 Docker 中用于列出 Docker 宿主机上所有的容器&#xff0c;包括正在运行的容器和已经停止的容器。这个命令是 Docker 用户常用的命令之一&#xff0c;用于查看和管理容器。 命令解析&#xff1a; docker&#xff1a;这是 Docker 的命令行接口&#xff…

Pytest-@pytest.fixture夹具篇(一)

一、定义 在Python的pytest测试框架中&#xff0c;pytest.fixture是一个&#xff08;不是唯一&#xff09;装饰器&#xff0c;用于定义一个测试夹具。 二、简单实例 使用参数autouserTrue pytest.fixture(autouseTrue) def my_fixture():print("Setup: 准备测试环境&q…

html导航栏logo

设置顶部logo <link rel"shortcut icon" href"图片路径" type"image/x-icon"> 显示效果&#xff1a; 这样设置可以是本地的&#xff0c;也可以是在线的。

【数学建模学习手册】python基本入门使用

本专栏内容为&#xff1a;数学建模原理 记录学习数学建模 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;数学建模 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学…

极米科技:走出舒适圈,推动数据架构现代化升级 | OceanBase 《DB大咖说》

《DB 大咖说》第 13 期&#xff0c;邀请到了极米科技软件与创新产品线高级架构师施刘凡来进行分享。 在小红书平台上&#xff0c;“是否应将家里的电视升级为投影仪&#xff1f;”这一话题激发了上百万篇笔记的分享与推荐&#xff0c;反映出年轻群体对投影仪的偏好。随着手机、…

【Linux】理解Linux中的软链接与硬链接

文章目录 理解Linux中的软链接与硬链接1. 什么是硬链接&#xff1f;示例&#xff1a; 2. 什么是软链接&#xff1f;示例&#xff1a; 3. 软链接与硬链接的对比4. 何时使用软链接与硬链接&#xff1f; 理解Linux中的软链接与硬链接 在Linux文件系统中&#xff0c;软链接&#x…