设计模式(行为型设计模式——观察者模式)

设计模式(行为型设计模式——观察者模式)

观察者模式

基本定义

  • 指多个对象间存在一对多的依赖关系,这样一来,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

  • 这种模式又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

模式结构

  • Subject 抽象主题 :也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

  • ConcreteSubject具体主题:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

  • Observer 观察者:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

  • ConcreteObserver 具体观察者:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

代码实现

Subject 抽象主题
/*** @Description 抽象主题类**/
public interface Subject {//注册观察者void registerObserve(Observe observe);//移除观察者void removeObserve(Observe observe);//通知观察者void notifyAllObserve();
}
ConcreteSubject 具体主题
/*** @Description 具体主题**/
@Slf4j
public class WeatherSubject implements Subject {List<Observe> observes = new ArrayList<>();Weather weather;/*** 实现特定顺序通知观察者,可以自我实现排序方式* 如果使用队列保存观者,需提前排序* @param observe*/@Overridepublic void registerObserve(Observe observe) {observes.add(observe);}@Overridepublic void removeObserve(Observe observe) {log.info("移除观察者 {}", observe.name());observes.remove(observe);}/*** 方式一、直接将更新内容发送给观察者* 推模式:通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。** 方式二、通知消息给观察者拉去更新数据* 拉模式:目标角色在发生变化后,仅仅告诉观察者角色“我变化了”;观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。**/@Overridepublic void notifyAllObserve() {if(observes.isEmpty()){log.info("暂无观察者");return;}observes.stream().forEach((observe)->{observe.update(weather);});}/*** 天气更新,通知观察者。* 与监听者模式差别在于 事件处理(事件源 + 事件 + 事件监听)* @param weather*/public void setWeather(Weather weather) {this.weather = weather;notifyAllObserve();//监听模式,事件处理。可以使用外观模式封装事件处理//eventHandle.notifyAllObserve(observes)}
}
POJO 普通Java实体:通知内容封装
@Data
public class Weather {private String date;private int temperature;private int humidity;private int windPower;public Weather(String date, int temperature, int humidity, int windPower) {this.date = date;this.temperature = temperature;this.humidity = humidity;this.windPower = windPower;}
}
Observer 观察者
/*** @Description 抽象观察者**/
public interface Observe {String name();/*** @param weather 天气*/void update(Weather weather);
}
ConcreteObserver 具体观察者
/*** @Description 具体观察者(APP客户端)**/
@Slf4j
public class AppClientObserve implements Observe {private Subject weatherSubject;//注册观察者, 关联主题public AppClientObserve(Subject weatherSubject) {this.weatherSubject = weatherSubject;this.weatherSubject.registerObserve(this);}@Overridepublic String name() {return "App客户端";}@Overridepublic void update(Weather weather) {log.info("APP客户端:{} 最新天气:温度 {} ℃, 相对湿度 {} %, 风力 {} 级",weather.getDate(), weather.getTemperature(), weather.getHumidity(), weather.getWindPower());}
}
/*** @Description 具体观察者(H5客户端)**/
@Slf4j
public class H5ClientObserve implements Observe {private Subject weatherSubject;//注册观察者, 关联主题public H5ClientObserve(Subject weatherSubject) {this.weatherSubject = weatherSubject;this.weatherSubject.registerObserve(this);}@Overridepublic String name() {return "H5客户端";}@Overridepublic void update(Weather weather) {log.info("H5客户端:{} 最新天气:温度 {} ℃, 相对湿度 {} %, 风力 {} 级",weather.getDate(), weather.getTemperature(), weather.getHumidity(), weather.getWindPower());}
}
Client 客户端:测试类
/*** @Description 观察者测试类**/
public class Test {public static void main(String[] args) {WeatherSubject weatherSubject = new WeatherSubject();Observe h5Observe = new H5ClientObserve(weatherSubject);Observe appObserve = new AppClientObserve(weatherSubject);weatherSubject.setWeather(new Weather("2020-4-16 12:00",24, 50, 2));weatherSubject.setWeather(new Weather("2020-4-16 16:00",20, 70, 3));weatherSubject.removeObserve(h5Observe);weatherSubject.setWeather(new Weather("2020-4-16 18:00",15, 65, 1));}
}
输出结果

H5客户端:2020-4-16 12:00 最新天气:温度 24 ℃, 相对湿度 50 %, 风力 2 级

APP客户端:2020-4-16 12:00 最新天气:温度 24 ℃, 相对湿度 50 %, 风力 2 级

H5客户端:2020-4-16 16:00 最新天气:温度 20 ℃, 相对湿度 70 %, 风力 3 级

APP客户端:2020-4-16 16:00 最新天气:温度 20 ℃, 相对湿度 70 %, 风力 3 级

移除观察者 H5客户端

APP客户端:2020-4-16 18:00 最新天气:温度 15 ℃, 相对湿度 65 %, 风力 1 级

优点

  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。

  • 目标与观察者之间建立了一套触发机制。

缺点

  • 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。

  • 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

总结

  • 观察者模式定义了对象之间的一对多关系。多个观察者监听同一个被观察者,当该被观察者的状态发生改变时,会通知所有的观察者。

  • 观察者与被观察者之间用松耦合方式结合。

  • 使用观察者模式,可以从被观察者处推或者拉数据。

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

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

相关文章

阿里云国际设置黑白名单(针对高防实例IP)

DDoS高防支持针对高防实例设置黑名单和白名单&#xff0c;以拦截或放行指定IP的访问请求&#xff0c;配置后对该实例所有的业务生效。本文九河云介绍如何配置黑白名单。 功能介绍 黑名单IP的访问流量将被DDoS高防实例直接丢弃。白名单IP的访问流量将被DDoS高防实例直接放行。…

ideaSSM 人才引进管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 人才引进管理系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff…

分布式链上随机数和keyless account

1. 引言 相关论文见&#xff1a; Aptos团队2024年论文 Distributed Randomness using Weighted VRFs 相关代码实现见&#xff1a; https://github.com/aptos-labs/aptos-core&#xff08;Rust&#xff09; 在链中生成和集成共享随机数&#xff0c;以扩展应用和强化安全。该…

G - Find a way

题目分析 1.双重bfs,遍历两个起点求最短路再计算总和即可 2.唯一的坑点在于对于一个KFC&#xff0c;两人中可能有一个到不了&#xff0c;所以还要对到不了的点距离做处理 #include <bits/stdc.h> using namespace std; using ll long long; const int N 220;struct pos…

交通事故档案管理系统|基于JSP技术+ Mysql+Java+Tomcat的交通事故档案管理系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

docker 修改日志存储路径

docker 日志默认存放在 /var/lib/docker/ 下 docker info修改步骤&#xff1a; 1、停止docker服务 systemctl stop docker 2、新建配置文件 vi /etc/docker/daemon.json添加如下内容 {"data-root": "/data/docker" }3、然后把之前的数据全部复制到新目…

python 之 装饰器(Decorators)

装饰器本质上也是一个函数&#xff0c;他可以让其他函数在不需要做任何代码变动的前提下&#xff0c;增加额外的功能&#xff0c;可以接受一个函数作为参数&#xff0c;并返回一个新的函数。 1. 装饰器的定义 装饰器的基本语法是使用符号&#xff0c;后面跟着装饰器的名称。这…

leetcode 494.目标和

思路&#xff1a;可以转化为背包问题。 首先我们看到&#xff0c;题目中要求我们求出目标数的方案数。既然有正数也有负数&#xff0c;那么就一定会从数组中选一部分当负数&#xff0c;选一部分当正数。 假如我们拿z当作选取当正数的元素的和&#xff0c;sum当作全部元素之和…

十、C#基数排序算法

简介 基数排序是一种非比较性排序算法&#xff0c;它通过将待排序的数据拆分成多个数字位进行排序。 实现原理 首先找出待排序数组中的最大值&#xff0c;并确定排序的位数。 从最低位&#xff08;个位&#xff09;开始&#xff0c;按照个位数的大小进行桶排序&#xff0c;将…

06 分页

文章目录 PageInfo PageInfo package com.aistart.tech.common;import java.io.Serializable; import java.util.List;public class PageInfo<T> implements Serializable {private Integer pageNum;//当前页private Integer pageSize;//每页显示条数private Integer pa…

将OpenCV与gdb驱动的IDE结合使用

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV4.9.0开源计算机视觉库在 Linux 中安装 下一篇&#xff1a;将OpenCV与gcc和CMake结合使用 ​ 能力 这个漂亮的打印机可以显示元素类型、、标志is_continuous和is_subm…

ClickHouse的表操作

1、背景 由于大数据平台需要对数据进行分析,因为ClickHouse是一个开源的列式数据库管理系统(DBMS)&#xff0c;专为联机分析处理(OLAP)而设计。 官方地址&#xff1a;ClickHouse 开发 | ClickHouse Docs 2、集群中的操作 在操作集群中的表的时候&#xff0c;最好是采用[dbn…

【设计模式】Java 设计模式之状态模式(State)

深入理解状态模式&#xff08;State&#xff09; 一、概述 状态模式是一种行为设计模式&#xff0c;它允许一个对象在其内部状态改变时改变它的行为。对象看起来好像修改了它的类。状态模式把所有的与一个特定的状态相关的行为放到一个类中&#xff0c;并且将请求委托给当前状…

5.79 BCC工具之tcpaccept.py解读

一,工具简介 tcpaccept工具用于追踪接受TCP套接字连接的内核函数(例如,通过accept()函数实现的被动连接;不是connect()函数)。 accept() 是一个在 UNIX-like 系统上用于套接字编程的系统调用,它在 TCP 服务器中起着关键作用。当 TCP 服务器通过 listen() 系统调用使其套…

蓝桥杯 全球变暖

Problem: 蓝桥杯 全球变暖 文章目录 思路解题方法复杂度Code 思路 这道题目可以使用深度优先搜索&#xff08;DFS&#xff09;或广度优先搜索&#xff08;BFS&#xff09;来解决。我们需要遍历整个地图&#xff0c;当遇到陆地&#xff08;‘#’&#xff09;时&#xff0c;就进行…

分块算法模板更新

基础模板&#xff08;区间修改&#xff0c;求区间和&#xff09; #include "bits/stdc.h" using namespace std; #define int long long const int N 100010;int sum[N],add[N],a[N],b[N]; int l[N],r[N];void change(int l1,int r1,int k) {int pb[l1],qb[r1];if(…

【Java常用API】简单爬虫练习题

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

0基础学习VR全景平台篇第146篇:为什么需要3D元宇宙编辑器?

一.什么是3D元宇宙编辑器&#xff1f; 3D元宇宙编辑器是全新3DVR交互渲染创作工具&#xff0c;集3D建模、虚拟展厅、AI数字人等能力&#xff0c;渲染和虚拟现实技术于一身的生产力工具。 具有跨平台和随时随地编辑等特点&#xff0c;可广泛应用于展会、展厅、博物馆、可视化园…

uniapp_微信小程序客服

一、调用api 二、代码 <button open-type"contact">客服</button> 三、小程序后台添加客服人员就行

Ubuntu学习笔记之Shell与APT下载工具

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ 一、Ubuntu Shell操作 简单的说Shell 就是敲命令。国内把 Linux 下通过命令行输入命令叫…