观察者模式(二十)

相信自己,请一定要相信自己

上一章简单介绍了迭代器模式(十九), 如果没有看过, 请观看上一章

一. 观察者模式

引用 菜鸟教程里面 观察者模式介绍: https://www.runoob.com/design-pattern/observer-pattern.html

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。

比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式

一.一 介绍

意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决: 一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用: 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决: 使用面向对象技术,可以将这种依赖关系弱化。

关键代码: 在抽象类里有一个 ArrayList 存放观察者们。

应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。


组成角色具体关系
抽象观察者角色Observer为所有的具体观察者定义一个接口,在得到主题通知时更新自己
具体观察者角色Baidu, Sina, User实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调
抽象被观察者角色Subject一个抽象主题,它把所有对观察者对象的引用保存在一个集合中
具体被观察者角色WeatherDataSubject一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知

image-20230615184354714

二. 观察者实例

如观察天气的情况

二.一 观察的对象实体 Weather

@Data
@Builder
public class Weather {/**温度, 气压, 湿度*/private float temperature;private float pressure;private float humidity;
}

二.二 抽象观察者 Observer

public interface Observer {public void update (Weather weather);
}

二.三 具体观察者实现

二.三.一 百度网站

@Slf4j
public class BaiDu implements Observer{private Weather weather ;@Overridepublic void update(Weather weather) {this.weather = weather;display();}public void display (){if (weather == null) {return ;}log.info(">>>>>>>>>>>>>百度网站获取到天气数据,进行个性化操作");log.info(">>>温度: {}, 气压: {}, 湿度: {}", weather.getTemperature(),weather.getPressure(),weather.getHumidity());}}

二.三.二 新浪网站

@Slf4j
public class Sina implements Observer{private Weather weather ;@Overridepublic void update(Weather weather) {this.weather = weather;display();}public void display (){if (weather == null) {return ;}log.info(">>>>>>>>>>>>>新浪网站获取到天气数据,进行个性化操作");log.info(">>>温度: {}, 气压: {}, 湿度: {}", weather.getTemperature(),weather.getPressure(),weather.getHumidity());}}

二.三.三 订阅者

@Slf4j
public class User implements Observer{private Weather weather ;@Overridepublic void update(Weather weather) {this.weather = weather;display();}public void display (){if (weather == null) {return ;}log.info(">>>>>>>>>>>>>订阅用户获取到天气数据,进行个性化操作");log.info(">>>温度: {}, 气压: {}, 湿度: {}", weather.getTemperature(),weather.getPressure(),weather.getHumidity());}}

二.四 抽象被观察者 Subject

public interface Subject {public void registerObserver(Observer observer);public void remove (Observer observer);public void notifyObservers();
}

二.五 具体观察者实现

@Slf4j
public class WeatherDataSubject implements Subject{private List<Observer> observerList = new ArrayList<>();private Weather weather;@Overridepublic void registerObserver(Observer observer) {observerList.add(observer);}@Overridepublic void remove(Observer observer) {observerList.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observerList) {observer.update(this.weather);}}public void setWeather(Weather weather) {this.weather = weather;dataChange();}public void dataChange() {// 更新后,数据发生了改变。log.info("获取到了最新的数据: {}", this.weather);notifyObservers();}
}

二.六 客户端调用

  @Testpublic void oneTest() {WeatherDataSubject weatherDataSubject = new WeatherDataSubject();weatherDataSubject.registerObserver(new BaiDu());weatherDataSubject.registerObserver(new Sina());// 设置数据weatherDataSubject.setWeather(Weather.builder().temperature(35.0f).pressure(20.0f).humidity(30.f).build());User user = new User();// 再添加个数据weatherDataSubject.registerObserver(user);weatherDataSubject.setWeather(Weather.builder().temperature(30.0f).pressure(21.0f).humidity(32.f).build());weatherDataSubject.remove(user);weatherDataSubject.setWeather(Weather.builder().temperature(32.0f).pressure(22.0f).humidity(33.f).build());}

image-20230615185146367

三. Java 实现观察者模式

Java 语言, 可以通过 Observer(Observer) Observable(Subject) 实现观察者处理

三.一 具体观察者和抽象观察者

@Slf4j
public class NewUser implements Observer {private String name;public NewUser(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {log.info("{} 观察到信息发生了变化 {}", name,arg);}
}

三.二 具体被观察者和抽象被观察者

public class NewWeatherDataSubject extends Observable {private Weather weather;public NewWeatherDataSubject (Weather weather) {this.weather = weather;}public void setWeather(Weather weather) {this.weather = weather;// 改变了super.setChanged();super.notifyObservers(weather);}
}

三.三 客户端调用

@Testpublic void twoTest() {Weather weather = Weather.builder().temperature(32.0f).pressure(22.0f).humidity(33.f).build();NewWeatherDataSubject newWeatherDataSubject = new NewWeatherDataSubject(weather);newWeatherDataSubject.addObserver(new NewUser("用户1"));newWeatherDataSubject.addObserver(new NewUser("用户2"));newWeatherDataSubject.addObserver(new NewUser("用户3"));log.info("温度发生改变");weather.setTemperature(34.f);newWeatherDataSubject.setWeather(weather);log.info("温度再次发生改变");weather.setTemperature(30.f);newWeatherDataSubject.setWeather(weather);}

image-20230615185508442


本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/Observer


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

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

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

相关文章

【MySQL】MySQL中SQL执行流程

文章目录 一、MySQL语句执行流程1.1、主要的原因有以下几点1.2、具体执行流程图如下 二、存储引擎三、MySQL的架构与内部模块四、崩溃恢复时如何判断事务是否需要提交 一、MySQL语句执行流程 连接器&#xff08;Connector&#xff09;&#xff1a; 当客户端发送一个连接请求时…

矩阵通引入AIGC,帮助企业挖掘用户线索

据CNNIC报告数据&#xff0c;截止2022年6月&#xff0c;我国网民规模达10.51亿&#xff0c;其中短视频用户规模为9.62亿&#xff0c;网络直播用户规模达7.16亿&#xff0c;占网民整体的68.1%。 庞大的用户体量为直播带货奠定了基础&#xff0c;给品牌商家提供了新流量阵地&…

自动刷新工具--可以自动编辑安居客房源信息

本工具可以自动刷新安居客的房源信息&#xff0c;不是爬虫&#xff0c;就是一款解放劳动力的RPA工具 使用方法&#xff1a; 1. 首先输入要自动刷新的房源id 2.点击 开始执行 如果需要免密登陆&#xff0c;需要在个人中心填上anjuke的账密 定时执行 声明&#xff1a;此工具只是…

我是怎么把win11一步一步变成Mac的

目录 【三指拖动】 【空格预览】 【切换Ctrl和Alt】 【使用Linux命令】 【其它】 之前很长一段时间在MacBook上面开发习惯了&#xff0c;然后因为一些原因现在换到了windows上面&#xff0c;不管是使用上还是系统上都很不习惯&#xff0c;因此做了一些改造&#xff0c;…

【Linux】应用层协议:HTTP和HTTPS

每个人都可以很喜欢每个人&#xff0c;但喜欢治不了病&#xff0c;喜欢买不了东西&#xff0c;喜欢不能当饭吃&#xff0c;喜欢很廉价… 文章目录 一、HTTP协议1.URL1.1 URL的组成1.2 urlencode && urldecode 2.HTTP协议格式2.1 http请求和响应的格式2.2 通过代码来进行…

Zookeeper集群的特点

一、Zookeeper集群的特点 Zookeeper:一个领导者 (Leader)&#xff0c;多个跟随者 (Follower) 组成的集群集群中只要有半数以上节点存活&#xff0c;Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器全局数据一致:每个Server保存一份相同的数据副本&#xff0c;C…

状态模式(State)

定义 状态是一种行为设计模式&#xff0c;让你能在一个对象的内部状态变化时改变其行为&#xff0c;使其看上去就像改变了自身所属的类一样。 前言 1. 问题 状态模式与有限状态机的概念紧密相关。 其主要思想是程序在任意时刻仅可处于几种有限的状态中。在任何一个特定状态…

Transformer中的Q,K,V

Query&#xff0c;Key&#xff0c;Value的概念取自于信息检索系统&#xff0c;举个简单的搜索的例子来说。当你在某电商平台搜索某件商品&#xff08;年轻女士冬季穿的红色薄款羽绒服&#xff09;时&#xff0c;你在搜索引擎上输入的内容便是Query&#xff0c;然后搜索引擎根据…

大数据分析的Python实战指南:数据处理、可视化与机器学习【上进小菜猪大数据】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 引言&#xff1a; 大数据分析是当今互联网时代的核心技术之一。通过有效地处理和分析大量的数据&#xff0c;企业可以从中获得有价值的洞察&#xff0c;以做出更明智的决策。本文将…

DAY 76 分布式监控平台:zabbix

市场上常用的监控软件&#xff1a; 传统运维&#xff1a;zabbix、 Nagios云原生环境&#xff1a; Prometheus &#xff08;go语言开发的&#xff09; zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去…

青大数据结构【2017】【综合应用、算法分析】

关键字&#xff1a; 平衡二叉树、平均查找长度、单链表、二叉树中序遍历非递归 三、综合应用 平衡二叉树AVL定义&#xff1a;任意节点的子树的高度差都小于等于 1 ASL&#xff08;12*24*3&#xff09;/717/7 四、算法分析

解决vmware虚拟机,克隆修改ip后,xshell连接不上问题

1、查看网卡 ifconfig2、修改网卡配置 vim /etc/sysconfig/network-scripts/ifcfg-ens32 改成与上图一样 修改后 3、重启reboot则解决