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

设计模式 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 总结

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • GD - EmbeddedBuilder - 给已有工程换MCU
  • C语言小游戏--贪吃蛇实现
  • 【B题第二套完整论文已出】2024数模国赛B题第二套完整论文+可运行代码参考(无偿分享)
  • Vue使用fetch获取本地数据
  • ESP32_获取心知天气
  • python之对象通过中介间接协作
  • Science|癌症中三级淋巴结构的免疫调节作用与治疗潜力|顶刊精析·24-09-08
  • mysql5.7安装
  • 用Pytho解决分类问题_DBSCAN聚类算法模板
  • Waline,一款开源博客-评论系统
  • 用Cri-O,Sealos CLI,Kubeadm方式部署K8s高可用集群
  • 【MySQL】MySQL常用的数据类型——表的操作
  • Linux下构建Docker镜像
  • mac 安装redis
  • 如何使用微软的Copilot AI工具将Word文档转换为PowerPoint
  • @angular/forms 源码解析之双向绑定
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 「面试题」如何实现一个圣杯布局?
  • CSS中外联样式表代表的含义
  • Git同步原始仓库到Fork仓库中
  • HTTP中的ETag在移动客户端的应用
  • Javascript设计模式学习之Observer(观察者)模式
  • JS函数式编程 数组部分风格 ES6版
  • Linux CTF 逆向入门
  • Making An Indicator With Pure CSS
  • nfs客户端进程变D,延伸linux的lock
  • PermissionScope Swift4 兼容问题
  • Shell编程
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 基于webpack 的 vue 多页架构
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 实现菜单下拉伸展折叠效果demo
  • 一个SAP顾问在美国的这些年
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #define与typedef区别
  • (C语言)fread与fwrite详解
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (动态规划)5. 最长回文子串 java解决
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (黑马点评)二、短信登录功能实现
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .Net 垃圾回收机制原理(二)
  • .NET分布式缓存Memcached从入门到实战
  • .Net语言中的StringBuilder:入门到精通