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

设计模式——观察者模式(Observer Pattern)+ Spring相关源码

文章目录

  • 一、观察者模式定义
  • 二、例子
    • 2.1 菜鸟教程例子
      • 2.1.1 定义观察者
      • 2.1.2 定义被观察对象
      • 2.1.3 使用
    • 2.2 JDK源码 —— Observable
      • 2.2.1 观察者接口Observer
      • 2.2.1 被观察者对象Observable
    • 2.3 Spring源码 —— AbstractApplicationContext
      • 2.3.1 观察者
      • 2.3.2 被观察者
    • 2.3 Guava源码 —— EventBus
  • 三、其他设计模式


一、观察者模式定义

类型:行为型模式
目的:当一个对象的状态发生改变时,其所有依赖者(观察者)都会收到通知并自动更新。


二、例子

2.1 菜鸟教程例子

2.1.1 定义观察者

//观察者
public abstract class Observer {//被观察对象protected Subject subject;public abstract void update();
}
public class BinaryObserver extends Observer{public BinaryObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); }
}
public class HexaObserver extends Observer{public HexaObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println( "Hex String: "  + Integer.toHexString( subject.getState() ).toUpperCase() ); }
}

2.1.2 定义被观察对象

import java.util.ArrayList;
import java.util.List;
//被观察对象 
public class Subject {//观察者列表private List<Observer> observers = new ArrayList<Observer>();private int state;public int getState() {return state;}public void attach(Observer observer){observers.add(observer);      }//通知所有观察者public void notifyAllObservers(){for (Observer observer : observers) {observer.update();}}  //修改数据时,通知所有观察者public void setState(int state) {this.state = state;notifyAllObservers();}
}

2.1.3 使用

public class ObserverPatternDemo {public static void main(String[] args) {//创建被观察对象Subject subject = new Subject();//创建观察者对象new HexaObserver(subject);new BinaryObserver(subject);//创建被观察对象调用setState时,通知国有观察者System.out.println("First state change: 15");   subject.setState(15);System.out.println("Second state change: 10");  subject.setState(10);}
}

2.2 JDK源码 —— Observable

2.2.1 观察者接口Observer

public interface Observer {void update(Observable o, Object arg);
}

2.2.1 被观察者对象Observable

public class Observable {private boolean changed = false;private Vector<Observer> obs;//添加观察者public synchronized void addObserver(Observer o) {if (o == null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}//通知观察者public void notifyObservers(Object arg) {Object[] arrLocal;synchronized (this) {if (!changed)return;arrLocal = obs.toArray();clearChanged();}for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}
}

2.3 Spring源码 —— AbstractApplicationContext

2.3.1 观察者

public class ContextStartedEvent extends ApplicationContextEvent {public ContextStartedEvent(ApplicationContext source) {super(source);}
}
public class ContextStoppedEvent extends ApplicationContextEvent {public ContextStoppedEvent(ApplicationContext source) {super(source);}
}
public class ContextRefreshedEvent extends ApplicationContextEvent {public ContextRefreshedEvent(ApplicationContext source) {super(source);}
}

2.3.2 被观察者

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {//观察者集合private Set<ApplicationEvent> earlyApplicationEvents;//添加观察者Eventpublic void publishEvent(ApplicationEvent event) {this.publishEvent(event, (ResolvableType)null);}//通知观察者Eventprotected void registerListeners() {Iterator var1 = this.getApplicationListeners().iterator();while(var1.hasNext()) {ApplicationListener<?> listener = (ApplicationListener)var1.next();this.getApplicationEventMulticaster().addApplicationListener(listener);}String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);String[] var7 = listenerBeanNames;int var3 = listenerBeanNames.length;for(int var4 = 0; var4 < var3; ++var4) {String listenerBeanName = var7[var4];this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {Iterator var9 = earlyEventsToProcess.iterator();while(var9.hasNext()) {ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();this.getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}
}

2.3 Guava源码 —— EventBus

public class EventBus {//注册订阅者(观察者)public void register(Object object) {this.subscribers.register(object);}//通知订阅者(观察者)public void post(Object event) {Iterator<Subscriber> eventSubscribers = this.subscribers.getSubscribers(event);if (eventSubscribers.hasNext()) {this.dispatcher.dispatch(event, eventSubscribers);} else if (!(event instanceof DeadEvent)) {this.post(new DeadEvent(this, event));}}
}

三、其他设计模式

创建型模式
结构型模式

  • 1、设计模式——装饰器模式(Decorator Pattern)+ Spring相关源码

行为型模式

  • 1、设计模式——访问者模式(Visitor Pattern)+ Spring相关源码
  • 2、设计模式——中介者模式(Mediator Pattern)+ JDK相关源码
  • 3、设计模式——策略模式(Strategy Pattern)+ Spring相关源码
  • 4、设计模式——状态模式(State Pattern)
  • 5、设计模式——观察者模式(Observer Pattern)+ Spring相关源码

相关文章:

设计模式——观察者模式(Observer Pattern)+ Spring相关源码

文章目录 一、观察者模式定义二、例子2.1 菜鸟教程例子2.1.1 定义观察者2.1.2 定义被观察对象2.1.3 使用 2.2 JDK源码 —— Observable2.2.1 观察者接口Observer2.2.1 被观察者对象Observable 2.3 Spring源码 —— AbstractApplicationContext2.3.1 观察者2.3.2 被观察者 2.3 G…...

openpnp - code review - 开机对话框历史记录和贡献者名单

文章目录 openpnp - code review - 开机对话框历史记录和贡献者名单概述笔记D:\my_openpnp\openpnp_dev_2022_0801\src\main\java\org\openpnp\gui\AboutDialog.javaEND openpnp - code review - 开机对话框历史记录和贡献者名单 概述 偶然发现, 自己打包后的openpnp, 开机后…...

JavaSE22——HashMap

集合框架_HashMap 一、概述 HashMap 是用于存储 Key-Value 键值对的集合。 &#xff08;1&#xff09;HashMap 根据键的 hashCode 值存储数据&#xff0c;大多数情况下可以直接定位到它的值&#xff0c;所以具有很快的访问速度&#xff0c;但遍历顺序不确定。 &#xff08;2&…...

「图像 merge」无中生有制造数据

在进行一个新项目的时候&#xff0c;往往缺少一些真实数据&#xff0c;导致没办法进行模型训练&#xff0c;这时候就需要算法工程师自行制作一些数据了&#xff0c;比如这篇文章分享的 bag 目标检测&#xff0c;在检测区域没有真实的 bag数据 此时&#xff0c;就可以采用图像拼…...

RK3588之ArmSoM-W3 + MPP实现多路硬解码拉流

简介 学习完MPP的解码Demo之后&#xff0c;想必大家都想通过一个项目来进行RK3588-MPP的解码实战。本篇文章就基于ArmSoM-W3开发板&#xff0c;开发一个多路硬解码项目&#xff0c;实现四路MPP硬解码拉流显示实现的效果如下&#xff1a; RK3588四路MPP硬解码拉流 环境介绍 硬件…...

【Rust日报】2023-10-29 隆重推出 Rerun 0.10!

Lapce代码编辑器发布v0.3.0 Lapce代码编辑器新发布v0.3.0&#xff01; https://lapce.dev/ 距离我们上次发布已经过去很长一段时间了。我们正忙着在自己的 UI 工具包Floem中重写 Lapce &#xff0c;这将使我们以后对 UI 部分代码的开发变得更容易、更快。 另一件值得注意的事情…...

AI智能识别如何助力PDF,轻松实现文档处理?

AI智能识别如何助力PDF&#xff0c;轻松实现文档处理&#xff1f; 随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;在各个领域都发挥着重要的作用。其中&#xff0c;文档智能&#xff08; Document AI &#xff09;在金融、医疗、教育、保险、能源、物流等…...

【SA8295P 源码分析】114 - 将Android GVM userdata文件系统从 EXT4 修改为 F2FS

【SA8295P 源码分析】114 - 将Android GVM userdata文件系统从 EXT4 修改为 F2FS 一、代码修改方法1. BoardConfig.mk2. 修改 fstab二、开机进入 adb 验证2.1 验证 userdata 修改 f2fs 文件系统格式成功2.2 测试 f2fs 文件系统性能:androbench.apk系列文章汇总见:《【SA8295P…...

LeetCode 387 字符串中的第一个唯一字符 简单

题目 - 点击直达 1. 387 字符串中的第一个唯一字符1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 387 字符串中的第一个唯一字符 1. 题目详情 给定一个字符串 s &#xff0c;找到 它的第一个不重复的字符&#xff0c;并返…...

线程池--简单版本和复杂版本

目录 一、引言 二、线程池头文件介绍 三、简单版本线程池 1.创建线程池 2.添加任务到线程池 3.子线程执行回调函数 4.摧毁线程池 5.简单版线程池流程分析 四、复杂版本线程池 1.结构体介绍 2.主线程 3.子线程 4.管理线程 一、引言 多线程版服务器一个客户端就需要…...

docker进阶

文章目录 docker 进阶Part1 常用命令总结docker version 查看docker客户端和服务端信息docker info 查看更加详细信息docker images 列出所有镜像基本用法常用选项 docker search 搜索镜像基本用法示例用法 docker pull 拉取镜像基本用法示例用法 docker rmi 删除镜像基本用法示…...

Unity HoloLens 2 应用程序发布

设置3D 启动器画面&#xff0c;glb格式的模型 VS中可以直接生成所有大小的图标...

3D RPG Course | Core 学习日记三:Navigation智能导航地图烘焙

前言 前面我们已经绘制好了一个简单的地图场景&#xff0c;现在我们需要使用Navigation给地图做智能导航&#xff0c;以实现AI自动寻路&#xff0c;以及设置地图的可行走区域以及不可行走区域&#xff0c;Navigation的基础知识、原理、用法在Unity的官方文档&#xff0c;以及网…...

Linux 启用本地ISO作为软件源

环境&#xff1a;sle12sp5 &#xff08;open SUSE&#xff09; 1、禁用现有的源 查看源&#xff1a;sle12sp5 zypper lr -u ➜ sle12sp5 zypper lr -u Repository priorities are without effect. All enabled repositories share the same prior…...

SpringCloud-Alibaba-Nacos2.0.4

SpringCloud-Alibaba-Nacos2.0.4 SpringCloud Alibaba版本选择&#xff08;截止到2023年3月12日&#xff09; Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2021.0.4.0*Spring Cloud 2021.0.42.6.11 SpringCloud Alibaba-2021.0.4.0组件版本关系 S…...

docker运行镜像相关配置文件

Dockerfile 文件配置 FROM anapsix/alpine-java:8_server-jre_unlimitedMAINTAINER Lion LiRUN mkdir -p /data/sydatasource/logs \/data/sydatasource/temp \/data/skywalking/agentWORKDIR /data/sydatasourceENV SERVER_PORT8220EXPOSE ${SERVER_PORT}ENV TZAsia/Shanghai …...

引擎系统设计思路 - 用户态与系统态隔离

用户态与系统态隔离&#xff1a; a. 外部用户侧的对象或者逻辑&#xff0c;在外部创建使用。内部系统侧的对象或者逻辑&#xff0c;在内部创建使用。 b. 用户状态下对内部系统的操作要立即响应&#xff0c;但是具体如何实际执行系统内部的机制&#xff0c;则是异步并行的。因为…...

致远OA wpsAssistServlet任意文件读取漏洞复现 [附POC]

文章目录 致远OA wpsAssistServlet任意文件读取漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 致远OA wpsAssistServlet任意文件读取漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利用…...

​轻量应用服务器有什么优势?如何评价亚马逊云科技轻量应用服务器?

什么是轻量应用服务器&#xff1f; 随着如今各行各业对云计算的需求越来越多&#xff0c;云服务器也被越来越多的企业所广泛采用。其中&#xff0c;轻量应用服务器是一种简单、高效、可靠的云计算服务&#xff0c;能够为开发人员、企业和个人提供轻量级的虚拟专用服务器&#…...

python的日志模块学习记录

logging模块是Python的内置日志模块满足日常需要 使用方法 *** 1.导入*** import logging from logging import config*** 2.配置日志配置项(基本配置一般不能满足需要&#xff0c;一般使用字典配置如下)*** # 日志基本配置方法&#xff0c;一般不能满足需要 logging.basic…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...