研磨设计模式day11观察者模式

目录

场景

代码示例

定义

观察者模式的优缺点

本质

何时选用

简单变型-区别对待观察者


场景

我是一家报社,每当我发布一个新的报纸时,所有订阅我家报社的读者都可以接收到

代码示例

报纸对象

package day11观察者模式;import java.util.Observable;/*** 报纸对象*/
public class NewsPaper extends Observable {/*** 报纸的内容*/private String content;/*** 获取报纸的具体内容* @return 报纸的具体内容*/public String getContent() {return content;}/*** 示意,设置报纸的具体内容,相当于要出版报纸了* @param content 报纸的具体内容*/public void setContent(String content) {this.content = content;// 内容有了,说明又出新报纸了,那就通知所有的读者this.setChanged();// 然后主动通知,用的推的方式this.notifyObservers(this.content);// 如果用拉的方式,这么调用
//        this.notifyObservers();}
}

读者,也就是观察者

package day11观察者模式;import java.util.Observable;
import java.util.Observer;/*** 真正的读者,也就是观察者*/
public class Reader implements Observer {/*** 读者的姓名*/private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {// 这里采用推的方式System.out.println(name + "收到报纸了,进行阅读。目标推过来的内容是===" + arg);// 这里是获取拉的数据
//        System.out.println(name + "收到报纸了,进行阅读。主动到目标对象去拉的内容是===" + ((NewsPaper)o).getContent());}
}

client

package day11观察者模式;/*** 客户端使用*/
public class Client {public static void main(String[] args) {// 1.创建一个报纸,作为被观察者NewsPaper subject = new NewsPaper();// 2.创建阅读者,也就是观察者Reader reader1 = new Reader();reader1.setName("张三");Reader reader2 = new Reader();reader2.setName("李四");Reader reader3 = new Reader();reader3.setName("王五");// 3.注册阅读者subject.addObserver(reader1);subject.addObserver(reader2);subject.addObserver(reader3);// 4.要出报纸啦subject.setContent("本期内容是观察者模式");}
}

 解析:

报社就是一个发布者,读者就是一个个订阅者,发布者提供订阅方法,每次发布者发布新的东西时,就会通知订阅者这条新的消息。

报社NewsPaper:它继承了Observable类,这个类包含了注册方法,提示改变,通知方式(推和拉)等方法,NewsPaper包含了报纸内容对象,get方法就不说了,set时会进行提示改变了,并主动通知,用的推的方式。

观察者Reader:它实现了Observer接口,实现了update方法,java实现观察者模式时默认是拉模型,如果使用推模型,那么在update这个方法里通过推拉的获取方式都可以获取到值

定义

类似发布订阅模式

观察者模式的优缺点

本质

观察者模式的本质:触发联动

在程序运行期间,通过这样的联动可以控制观察者,在update执行的时候。

何时选用

简单变型-区别对待观察者

举例:根据水质污染的严重程度来分别告知不同的管理者

思路:将水质污染当作被观察的目标,监测员、预警人员和领导就是观察者。在目标里面进行判断,满足就通知,不满足不通知。

观察者接口

1.被通知的方法2.设置观察人员的职务3.获取观察人员的职务

package day11观察者模式.高级;/*** 水质观察者接口定义*/
public interface WatcherObserver {/*** 被通知的方法* @param subject 传入被观察的目标对象*/public void update(WaterQualitySubject subject);/*** 设置观察人员的职务* @param job*/public void setJob(String job);/*** 获取观察人员的职务* @return*/public String getJob();}

观察者的具体实现

package day11观察者模式.高级;public class Watcher implements WatcherObserver{private String job;@Overridepublic void update(WaterQualitySubject subject) {// 这里采用拉的方式System.out.println(job + "获取到通知,当前污染级别为: " + subject.getPolluteLevel());}@Overridepublic void setJob(String job) {this.job = job;}@Overridepublic String getJob() {return job;}
}

目标的父对象(抽象类) :1.定义抽象是因为我们不需要全部都发消息,所以让子类去根据业务的实际需要自己去选择性的通知。2.而且在我们传入目标对象的时候具有很好的封装性,不需要对外展示具体的目标对象,传给观察者的只是目标的父抽象类。

package day11观察者模式.高级;import java.util.ArrayList;
import java.util.List;/*** 定义目标的父对象*/
public abstract class WaterQualitySubject {/*** 用来保存注册的观察者对象*/protected List<WatcherObserver> observers = new ArrayList<WatcherObserver>();/*** 注册观察者对象* @param observer  观察者对象*/public void attach(WatcherObserver observer){observers.add(observer);}/*** 删除观察者对象* @param observer*/public void detach(WatcherObserver observer){observers.remove(observer);}/*** 通知对应的观察者对象*/public abstract void notifyWatchers();/*** 获取水质污染的级别*/public abstract int getPolluteLevel();
}

目标的实现(继承目标父抽象类)

package day11观察者模式.高级;/*** 具体的检测对象*/
public class WaterQuality extends WaterQualitySubject{/*** 污染的级别,0正常 1轻度污染 2中度污染 3高度污染*/private int polluteLevel = 0;/*** 获取水质污染的级别* @return*/@Overridepublic int getPolluteLevel() {return polluteLevel;}/*** 当检测水质情况后,设置水质污染的级别* @param polluteLevel 水质污染的级别*/public void setPolluteLevel(int polluteLevel) {this.polluteLevel = polluteLevel;// 通知相应的观察者this.notifyWatchers();}/*** 通知相应的观察者对象*/@Overridepublic void notifyWatchers() {// 循环所有注册的观察者for (WatcherObserver watcher : observers) {// 开始根据污染级别判断都通知谁if (this.polluteLevel >= 0 ){// 通知监测员做记录if ("监测人员".equals(watcher.getJob())){watcher.update(this);}}if (this.polluteLevel >= 1 ){// 通知监测员做记录if ("预警人员".equals(watcher.getJob())){watcher.update(this);}}if (this.polluteLevel >= 2 ){// 通知监测员做记录if ("领导".equals(watcher.getJob())){watcher.update(this);}}}}}

client

package day11观察者模式.高级;public class Client {public static void main(String[] args) {// 创建具体的检测对象WaterQuality subject = new WaterQuality();// 创建几个观察者Watcher watcher1 = new Watcher();watcher1.setJob("监测人员");Watcher watcher2 = new Watcher();watcher2.setJob("预警人员");Watcher watcher3 = new Watcher();watcher3.setJob("领导");// 注册观察者subject.attach(watcher1);subject.attach(watcher2);subject.attach(watcher3);// 填写水质报告System.out.println("水质正常---");subject.setPolluteLevel(0);System.out.println("轻度污染---");subject.setPolluteLevel(1);System.out.println("重度污染---");subject.setPolluteLevel(2);}
}

解析:

从client开始,先创建了具体的检测对象, 他有什么用呢?可以注册观察者,可以发布通知

创建了几个观察者实现对象,给他们赋予了不同的职务。

将观察者跟目标对象进行关联,也就是注册,点进去看一下,调用了attach方法,这个方法不是具体的检测对象本身的,而是它的抽象父类中的方法

都注册进去之后,目标对象开始运行,他现在出了一个水质为0的污染报告,这个时候应该传递给谁信息呢?

 

点进这个setPolluteLevel(0)看一下 。这个是具体的检测对象本身的方法。

可以看出首先将传过来的值赋值给当前对象,然后调用了 this.notifyWatchers()方法。我们接着往下。

进来这个方法后,遍历所有注册到目标对象的观察者(订阅了该目标对象的订阅者),这个observers哪里来的?(),是注册而来的。

接着判断属于哪一类的污染,此时过来的污染为0,就判断当前观察者的职务是不是检测人员,如果是就调用update更新的方法,如果不是就不用管。

我们看一下update,被通知方法的接口

 接下来看看它的实现

 解析:判断是不是检测人员,如果是我就给他发送消息(它就能接收到消息)。

如果污染为1,那么就满足两个条件,就会给预警人员和检测人员都发送消息

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

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

相关文章

扫雷小游戏

目录 一.扫雷小游戏 二.游戏主体一览 ​编辑 三.模块化设计扫雷游戏 3.1打印欢迎菜单 3.2创建两个二维数组 3.3棋盘稍加修改 3.4布置雷 3.5排查雷 四.游戏总体代码 4.1game.h头文件 4.2game.c函数实现源文件 4.3游戏main函数主体 五.游戏效果图 一.扫雷小游戏 这是…

建设全球研发中心城市,长沙政协将会发挥怎样的作用?

政协力量&#xff0c;会如何推动一座城市的发展&#xff1f;在全国各大城市都力“拼经济、搞创新”的时代大背景下&#xff0c;人民政协的力量会如何助推长沙建设全球研发中心城市呢&#xff1f; 这是笔者此前一直很好奇的两个问题。8月24日&#xff0c;一场由长沙市政协举办的…

FFmpeg解码32k大分辨率出现如下错误:Picture size 32768x32768 is invalid

最近找到一张32k的jpeg图片&#xff0c;尝试用ffmpeg来进行解码&#xff0c;命令如下&#xff1a; ffmpeg -i enflame_32768-32768-420.jpg 32.yuv结果出现Picture size 32768x32768 is invalid的错误&#xff1a; 找到报错的代码文件imgutils.c&#xff0c;以及函数&#x…

字符串经典问题

1. 验证回文串 验证回文串 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xff0c;如果它是 回文串 &#xff0c;返回 t…

项目部署之后页面没有刷新怎么办?

最近项目部署成功之后&#xff0c;突然产品找我&#xff0c;上线之后&#xff0c;页面没有生效&#xff0c;这是怎么回事&#xff1f;我这是第一次部署这个项目,也不太清楚历史问题,接下来就慢慢寻找答案吧, 如果心急的可以直接看后面的总结&#xff0c;下面我们好好聊聊缓存的…

【RuoYi移动端】uniApp导入和引用uView2.0插件

一、打开uiew官网 安装 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架uView UI&#xff0c;是 uni-app 生态最优秀的 UI 框架&#xff0c;全面的组件和便捷的工具会让您信手拈来&#xff0c;如鱼得水https://uviewui.com/components/install.html 也可直…

基于Java+SpringBoot+Vue前后端分离在线考试与学习交流网页平台设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

SpringSession

Spring Session 是 Spring 的项目之一。Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案&#xff0c;默认采用外置的 Redis 来存储 Session 数据&#xff0c;以此来解决 Session 共享的 问题。(springsession储存session数据的方式有很多&#xff0c;我们常…

excel中两列数据生成折线图

WPS中excel的两列数据&#xff0c;第一列为x轴&#xff0c;第二列为y轴&#xff0c;生成折线图&#xff0c;并生成拟合函数。 1.选中两列数据&#xff0c;右击选择插入图表&#xff0c;选择XY&#xff08;散点图&#xff09;&#xff0c;生成散点折线图 2.选中图中散点&#x…

SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)

一、spring cloud简介 spring cloud 为开发人员提供了快速构建分布式系统的一些工具&#xff0c;包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单&#xff0c;可以在开发人员的电脑上跑。另外说明spring cloud是基…

Web服务器基础 http协议

文章目录 1.Web基础1.1MIME1.2 URI 和 URL1.2.1定义1.2.2两者的区别 2.静态资源和动态资源2.1 静态资源2.2 动态资源 3.HTTP协议3.1HTTP协议简介3.2HTTP协议的版本及区别3.2.1http协议版本3.2.2http1.0和1.1的区别 3.3HTTP请求报文3.4HTTP请求访问的过程1、建立连接&#xff1a…

服务器CPU飚高排查

排查思路 当正在运行的Java服务导致服务器的CPU突然飙高时&#xff0c;我们该如何排查定位到哪个接口的哪行代码导致CPU飙高的问题呢&#xff1f;我主要提供两个方案&#xff1a; jstackarthas 准备工作 代码准备 现在需要准备一段可以让服务器CPU飙高的代码以及把代码部署…

Go framework-Kratos

目录 一、Go framework 1、Kratos 介绍 1.1、Kratos 框架开发依赖安装 2、初始化 Kratos 项目 3、使用 Protobuf 、生成 Go 代码 3.1、增加proto文件模板 3.2、修改proto文件模板 3.3、根据修改完的模板文件生成客户端代码 3.4、根据修改完的模板文件生成服务端代码 …

Windows平台Unity下播放RTSP或RTMP如何开启硬解码?

我们在做Windows平台Unity播放RTMP或RTSP的时候&#xff0c;遇到这样的问题&#xff0c;比如展会、安防监控等场景下&#xff0c;需要同时播放多路RTMP或RTSP流&#xff0c;这样对设备性能&#xff0c;提出来更高的要求。 虽然我们软解码&#xff0c;已经做的资源占有非常低了…

在外SSH远程连接macOS服务器

文章目录 前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址 5. 使用固定TCP端口地址ssh远程 …

MySQL—MySQL的NULL值是怎么存放的

一、引言 1、MySQL数据存放在哪个文件&#xff1f; 创建一个数据库会产生三种格式的文件&#xff0c;分别是.opt格式、.frm格式、.ibd格式。 opt格式&#xff1a;用来存储当前数据库的默认字符集和字符校验规则。 frm格式&#xff1a;该文件是用来保存每个表的元数据信息的&…

ChatGPT⼊门到精通(1):ChatGPT 是什么

⼀、直观感受 1、公司 OpenAI&#xff08;美国&#xff09; 2、官⽅⽹站 3、登录ChatGPT ![在这里插入图片描述](https://img-blog.csdnimg.cn/26901096553a4ba0a5c88c49b2601e6a.png 填⼊帐号、密码&#xff0c;点击登录。登录成功&#xff0c;如下 3、和ChatGPT对话 开始…

Llama-2大模型本地部署研究与应用测试

最近在研究自然语言处理过程中&#xff0c;正好接触到到大模型&#xff0c;特别是在年初chatgpt引来的一大波AIGC热潮以来&#xff0c;一直都想着如何利用大模型帮助企业的各项业务工作&#xff0c;比如智能检索、方案设计、智能推荐、智能客服、代码设计等等&#xff0c;总得感…

四信5G智慧交通方案

5G是第五代移动通信技术的简称&#xff0c;是具有高速率低时延和大连接特点的新一代宽带移动通信技术&#xff0c;是实现智慧交通中的“车、路、人、环境”等交通要素互联互通的网络基础设施。相比以往的移动通信网络&#xff0c;5G网络以一种灵活部署的架构提供10Gbps以上的带…

Python中的API构建指南:在Flask中进行API开发

原文&#xff1a;Python中的API构建指南&#xff1a;在Flask中进行API开发 - 知乎 如何实现从一个软件与另一个软件的通信交互&#xff1f;就像我们的APP&#xff0c;如何实现微信支付、苹果支付&#xff1f; 其实&#xff0c;我们只需要一个API。 API&#xff08;应用程序编…