行为型-观察者模式
文章目录
- 基本概念
- 定义
- 使用场景
- 代码实现
- 延伸阅读
- java监听机制
- spring监听机制
基本概念
定义
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。
观察者模式包含以下几个核心角色:
主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。
观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。
具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。
观察者模式通过将主题和观察者解耦,实现了对象之间的松耦合。当主题的状态发生改变时,所有依赖于它的观察者都会收到通知并进行相应的更新。
使用场景
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。通过这种事件触发的机制,将观察者和被观察者进行解耦。
注意事项:
1、JAVA 中已经有了对观察者模式的支持类。(Java中EventObject、EventListener)
2、避免循环引用。
3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
代码实现
主题接口
/*** 抽象主题(抽象被观察者角色)*/
public interface Subject {/*** 所有抽象观察者角色的集合*/List<Observer> observerList = Lists.newArrayList();/*** 注册观察者* @param observer*/default void addObserver(Observer observer){observerList.add(observer);}/*** 取消注册* @param observer*/default void removeObserver(Observer observer){observerList.remove(observer);}/*** 通知所有观察者* @param content*/default void notifyAllObserver(String content){for (Observer observer: observerList){observer.recvMsg(content);}}}
观察者接口
/*** 观察者*/
public interface Observer {void recvMsg(String content);
}
具体被观察者
@Data
public class ConcreteSubject implements Subject<Observer> {private String msg;/*** 发送通知*/public void sendMsg(){System.out.println("ConcreteSubject send msg: " + this.msg);notifyAllObserver(msg);}
}
具体观察者
public class ConcreteObserver implements Observer {@Overridepublic void recvMsg(String content) {System.out.println("ConcreteObserver recv msg:" + content);}
}
测试
public class ObserverTest {public static void main(String[] args) {ConcreteSubject concreteSubject = new ConcreteSubject();concreteSubject.setMsg("important msg");concreteSubject.addObserver(new ConcreteObserver());concreteSubject.sendMsg();}
}
延伸阅读
java监听机制
一、创建事件对象
public class MusicEvent extends EventObject {public static final int STATE_OPEN = 1;public static final int STATE_CLOSE = -1;/*** 状态*/private int state;/*** Constructs a prototypical Event.** @param source the object on which the Event initially occurred* @throws IllegalArgumentException if source is null*/public MusicEvent(Object source) {super(source);}public MusicEvent(Object source, int state) {super(source);this.state = state;}public int getState() {return state;}public void setState(int state) {this.state = state;}
}
二、创建监听器
public interface MusicListener extends EventListener {void play(MusicEvent musicEvent);
}
CloseMusicListener实现
public class CloseMusicListener implements MusicListener{@Overridepublic void play(MusicEvent musicEvent) {if(musicEvent.getState() == MusicEvent.STATE_CLOSE){System.out.println("CloseMusicListener play: stop dance");}}
}
OpenMusicListener实现
public class OpenMusicListener implements MusicListener{@Overridepublic void play(MusicEvent musicEvent) {if(musicEvent.getState() == MusicEvent.STATE_OPEN){System.out.println("OpenMusicListener play: let us go dancing!");}}
}
三、定义事件源,管理监听器
public class EventSource {// 监听器列表,监听器注册入此列表public List<MusicListener> musicListenerList = new ArrayList<>();// 注册监听器public void addMusicListener(MusicListener musicListener) {musicListenerList.add(musicListener);}// 取消注册public void removeMusicListener(MusicListener musicListener) {musicListenerList.remove(musicListener);}// 接收外部事件public void notifyMusicListener(MusicEvent musicEvent) {for (MusicListener musicListener : musicListenerList){musicListener.play(musicEvent);}}
}
四、测试
public class MusicEventTest {public static void main(String[] args) {EventSource eventSource = new EventSource();eventSource.addMusicListener(new OpenMusicListener());eventSource.addMusicListener(new CloseMusicListener());eventSource.notifyMusicListener(new MusicEvent("开门事件", MusicEvent.STATE_OPEN));}
}
spring监听机制
一、创建事件对象,继承ApplicationEvent
@EqualsAndHashCode(callSuper = true)
public class MyEvent extends ApplicationEvent {private String context;public MyEvent(Object source) {super(source);}public String getContext() {return context;}public void setContext(String context) {this.context = context;}
}
二、定义监听器,实现ApplicationListener
MyApplication1
public class MyApplication1 implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent myEvent) {System.out.println("MyApplication1 event:" + myEvent.getContext());}
}
MyApplication2
public class MyApplication2 implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent myEvent) {System.out.println("MyApplication2 event:" + myEvent.getContext());}
}
三、事件通知
@Service
public class MyListenerService {@Autowiredprivate ApplicationEventPublisher applicationEventPublisher;public void register(MyEvent event){applicationEventPublisher.publishEvent(event);}
}
相关文章:

行为型-观察者模式
文章目录 基本概念定义使用场景代码实现 延伸阅读java监听机制spring监听机制 基本概念 定义 观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。 观察者模式…...

《ElementPlus 与 ElementUI 差异集合》el-input 和 el-button 属性 size 有变化
差异 ** element-ui el-input、el-input-number 和 el-button 中,属性size 值是 medium / small / minielement-plus el-input、el-input-number 和 el-button 中,属性size 值是 large / default /small 如果你是自动升级,Vue3 系统会有如…...

pxe安装mini centos系统
一、准备工作 1、关闭防火墙和selinux systemctl stop firewalld && systemctl disable firewalldsetenforce 02、配置静态ip 需要在dhcp里面填写tftp配置,所以需要固定ip 二、dhcp安装配置 作用:给客户端提供ip地址,并告诉客户…...

Android studio 性能调试
一、概述 Android studio 的Profiler可用来分析cpu和memory问题,下来进行说明介绍。 二、Android studio CPU调试 从开发模拟器或设备中启动应用程序; 在 Android Studio 中,通过选择View > Tool Windows > Profiler启动分析器。 应…...

java8特性 stream流中map函数的使用
map 函数的作用就是针对管道流中的每一个数据元素进行转换操作。 例如 将集合中的每一个字符串,全部转换成大写! List<String> collect alpha.stream().map(String::toUpperCase).collect(Collectors.toList()); //上面使用了方法引用…...

【Emgu CV教程】9.5、形态学常用操作之形态学梯度
文章目录 一、相关概念1.什么叫形态学梯度2.形态学梯度的函数 二、演示1.原始素材2.代码3.运行结果 一、相关概念 1.什么叫形态学梯度 形态学梯度,就是用膨胀的原始图像减去腐蚀的原始图像,所以它的特性就是去除前景物体的内部区域,只得到前…...

算法笔记之蓝桥杯pat系统备考(2)
算法笔记之蓝桥杯&pat系统备考(1) 文章目录 五、数学问题5.2最大公约数和最小公倍数5.2.1最大公约数5.2.2最小公倍数 5.3分数的四则运算5.3.1分数的表示与化简5.3.2分数的四则运算5.3.3分数的输出 5.4素数(质数)5.4.1[素数的…...

基于SpringBoot+Druid实现多数据源:注解+编程式
前言 本博客姊妹篇 基于SpringBootDruid实现多数据源:原生注解式基于SpringBootDruid实现多数据源:注解编程式基于SpringBootDruid实现多数据源:baomidou多数据源 一、功能描述 配置方式:配置文件中配置默认数据源,…...

已解决org.apache.zookeeper.KeeperException.BadVersionException异常的正确解冲方法,亲测有效!!!
已解决org.apache.zookeeper.KeeperException.BadVersionException异常的正确解冲方法,亲测有效!!! 目录 问题分析 报错原因 解决思路 解决方法 总结 博主v:XiaoMing_Java 问题分析 在使用Apache ZooKeeper进行…...

数据结构:堆
堆的概念 1.堆是一个完全二叉树 2.小堆(任何一个父亲<孩子),大堆(任何一个父亲>孩子) 堆的结构 物理结构:数组 逻辑结构:二叉树 #pragma once #include<assert.h> #include<iostream> typedef int HPDataType; typedef struct Heap {HPDataType* _a;int…...

CSS中三栏布局的实现
三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现: 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。 .outer {position: relative;h…...

Linux搭建我的世界(MC)整合包服务器,All the Mods 9(ATM9)整合包开服教程
Linux使用MCSM面板搭建我的世界(Minecraft)整合包服务器,MC开服教程,All the Mods 9(ATM9)整合包搭建服务器的教程。 本教程使用Docker来运行mc服,可以方便切换不同Java版本,方便安装多个mc服版本。 视频教程:https:…...

让数据在业务间高效流转,镜舟科技与NineData完成产品兼容互认
近日,镜舟科技与NineData完成产品兼容测试。在经过联合测试后,镜舟科技旗下产品与NineData云原生智能数据管理平台完全兼容,整体运行高效稳定。 镜舟科技致力于帮助中国企业构建卓越的数据分析系统,打造独具竞争力的“数据护城河”…...

2.1HTML5基本结构
HTML5实际上不算是一种编程语言,而是一种标记语言。HTML5文件是由一系列成对出现的元素标签嵌套组合而成,这些标签以<元素名>的形式出现,用于标记文本内容的含义。浏览器通过元素标签解析文本内容并将结果显示在网页上,而元…...

设置浏览器显示小于12px以下字体
问题 我们在项目开发过程中有时候会遇到设计师给的小于12px的字体,IE、火狐浏览器、移动端等小于12px的字号大小还是可以正常显示的,但是谷歌浏览器上显示字体最小为12px,css设置font-size:10px,运行代码显示结果仍然…...

web蓝桥杯真题:成语学习
代码: //TODO 点击文字后,在idiom从左到右第一个空的位置加上改文字 getSingleWord(val) {let index this.idiom.indexOf() //从左往右查询空字符串this.$set(this.idiom, index, val) //响应式更新 },// TODO 校验成语是否输入正确答案 confirm…...

外包干了5天,技术明显退步。。。。。
先说一下自己的情况,本科生,19年通过校招进入南京某软件公司,干了接近2年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了2年的功能测试&…...

Vue:自定义消息通知组件
一、效果描述 在JS中使用一个Message函数,弹出一个自定义的消息框。 效果体验:缓若江海凝清光 二、实现方式 1.新建一个消息组件 2.新建一个js文件,新建一个需要导出函数 3.在函数中新建一个Vue实例,并将消息组件挂载上去。…...

2023 收入最高的十大编程语言
本期共享的是 —— 地球上目前已知超过 200 种可用的编程语言,了解哪些语言在 2023 为开发者提供更高的薪水至关重要。 过去一年里,我分析了来自地球各地超过 1000 万个开发职位空缺,辅助我们了解市场,以及人气最高和收入最高的语…...

Github 2024-03-11 开源项目周报 Top15
根据Github Trendings的统计,本周(2024-03-11统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4TypeScript项目3Jupyter Notebook项目3C#项目1HTML项目1CSS项目1Dart项目1Lua项目1Shell项目1Rust…...

【DAY10 软考中级备考笔记】数据结构 图
数据结构 图 3月11日 – 天气:晴 晚上无线网络突然不能用了,花费好久弄这个,耽误了一些时间 1. 图的定义 这里需要注意完全图的定义,以及完全图的边数 这里需要注意连通图和连通分量的概念。 2. 图的存储结构 图有两种存储结构&a…...

java-ssm-jsp基于java的餐厅点餐系统的设计与实现
java-ssm-jsp基于java的餐厅点餐系统的设计与实现 获取源码——》公主号:计算机专业毕设大全...

蓝桥杯(1):python排序
1 基础 1.1 输出 1.1.1 去掉输出的空格 print("Hello","World",123,sep"") print("hello",world,123,sep) print(hello,world,123) #输出结果 #HelloWorld123 #helloworld123 #hello world 123 1.1.2 以不同的方式结尾 print(&quo…...

SpringMVC请求、响应和拦截器的使用
SpringMVC请求 RequestMapping注解 RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系 RequestMapping注解可以作用在方法和类上 1. 作用在类上:第一级的访问目录 2. 作用在方法上:第二级的访问目录 3. 细节:路径可以不编写…...

基于springboot+layui仓库管理系统设计和实现
基于 java springbootlayui仓库管理系统设计和实现 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取…...

【开源-土拨鼠充电系统】鸿蒙 HarmonyOS 4.0+微信小程序+云平台
本人自己开发的开源项目:土拨鼠充电系统 ✍GitHub开源项目地址👉:https://github.com/cheinlu/groundhog-charging-system ✍Gitee开源项目地址👉:https://gitee.com/cheinlu/groundhog-charging-system ✨踩坑不易&am…...

[抽象]工厂模式([Abstract] Factory)——创建型模式
[抽象]工厂模式——创建型模式 什么是抽象工厂? 抽象工厂模式是一种创建型设计模式,让你能够保证在客户端程序中创建一系列有依赖的对象组时,无需关心这些对象的类型。 具体来说: 对象的创建与使用分离: 抽象工厂模…...

QT网络编程之实现UDP广播发送和接收
推荐一个不错的人工智能学习网站,通俗易懂,内容全面,作为入门科普和学习提升都不错,分享一下给大家:前言https://www.captainbed.cn/ai 一.UDP通信 1.QT中实现UDP通信主要用到了以下类:QUdpSocket、QHost…...

SSL VPN基础原理
目录 SSL ---安全传输协议(安全套接层)---TLS ----传输层安全协议 SSL的工作原理 SSL会话建立的过程 编辑 数据传输过程中的封装示意图 无客户端认证的过程 有客户端认证的过程 SSL VPN的核心技术---虚拟网关技术 服务器验证的点: 资源…...

深入理解FTP协议:文件传输的桥梁
深入理解FTP协议:文件传输的桥梁 在数字化时代,文件传输协议(FTP)是互联网上进行文件交换的重要手段。FTP允许用户在不同的计算机之间传输文件,无论是上传还是下载,都提供了一种稳定且高效的方式。本文将深…...