03-JAVA设计模式-观察者模式

ops/2025/1/16 0:02:38/

观察者模式

什么是观察者模式

Java中的观察者模式是一种常见的设计模式,它允许对象(观察者)订阅另一个对象(被观察者)的状态变化,并在状态变化时自动得到通知。

核心:
观察者模式主要用于1:N的通知。当一个对象(目标对象)的状态发生变化时,它需要及时告知一系列对象(观察者对象)令他们做出响应。

通知观察者的方式:

  • 推:
    • 每次都会把通知以广播的方式发送给所有观察者,所有观察者只能被动接收。
  • 拉:
    • 观察者只要知道有情况即可。至于什么时候获取内容,获取什么内容都可以自主决定。

优点:

  • 解耦:观察者模式降低了对象之间的耦合度,使得它们可以独立地改变和复用。
  • 扩展性:新的观察者可以很容易地加入到现有系统中,而无需修改其他部分的代码。
  • 灵活性:观察者模式允许在运行时动态地改变观察者和被观察者的关系。

缺点:

  • 开发和调试复杂:由于系统中存在多个观察者和被观察者,开发和调试可能会变得相对复杂。
  • 性能问题:如果观察者数量庞大,或者被观察者状态改变频繁,可能会导致性能下降。
  • 消息通知顺序:在Java中,消息的通知一般是顺序执行的,一个观察者卡顿可能会影响整体的执行效率。

常见场景:

  • 图形用户界面(GUI)开发:在GUI应用程序中,当用户与界面进行交互(例如点击按钮或拖动滑块)时,界面的某些部分可能需要更新以反映这些变化。观察者模式允许这些部分(观察者)自动响应这些事件,而无需手动调用更新方法。
  • 游戏开发:在游戏中,玩家和NPC的行为,如移动、攻击、受伤等,都可能触发一系列事件。观察者模式可以用来注册和通知这些事件的监听器,以便游戏逻辑能够实时响应并更新游戏状态。
  • 消息传递系统:在分布式系统或微服务架构中,组件之间需要传递消息以实现通信和协作。观察者模式允许一个组件(被观察者)在产生消息时通知所有订阅了该消息的组件(观察者),从而实现高效的消息传递。
  • 实时数据监控:在需要实时跟踪和响应数据变化的场景中,如股票价格监控、传感器数据读取等,观察者模式可以帮助实现当数据变化时自动触发相应的处理逻辑。
  • 状态管理:当应用程序中某个对象的状态发生变化,并且需要通知其他对象进行相应的处理时,可以使用观察者模式。例如,一个订单状态的改变可能需要通知库存系统、支付系统等多个系统进行相应的操作。

案例1

推方式实现,以广播方式发送消息所有观察者

UML

在这里插入图片描述

实现步骤:

  • 创建观察者接口,定义通过被观察者更新状态接口
  • 创建被观察者,被观察者持有所有观察者的引用,提供注册、移除、通知所有观察者的方法,定义状态属性,提供get/set方法set方法中默认通知所有观察者

实现代码

Observer.java

java">// 观察者接口
public interface Observer {void update(Subject subject);
}

Subject.java

java">import java.util.ArrayList;
import java.util.List;// 被观察者
public class Subject {// 定义存储观察者的集合private List<Observer> observerList = new ArrayList<Observer>();// 定义状态属性private String state;// 注册观察者public void registerObserver(Observer observer){observerList.add(observer);}// 移除观察者public void removeObserver(Observer observer){observerList.remove(observer);}// 通知所有观察者public void notifyObservers(){for(Observer observer : observerList){observer.update(this);}}public String getState() {return state;}public void setState(String state) {this.state = state;notifyObservers();}
}

ObserverA.java

java">// 观察者A
public class ObserverA implements Observer{@Overridepublic void update(Subject subject) {System.out.printf("观察者A接收到消息-state:%s%n",subject.getState());}
}

ObserverB.java

java">// 观察者B
public class ObserverB implements Observer{@Overridepublic void update(Subject subject) {System.out.printf("观察者B接收到消息-state:%s%n",subject.getState());}
}

TestClient.java

java">public class TestClient {public static void main(String[] args) {Subject subject = new Subject();subject.registerObserver(new ObserverA());subject.registerObserver(new ObserverB());subject.setState("START");}
}

执行结果:

在这里插入图片描述

案例2

使用java.util提供的Observable,Observer类实现案例1。

该方式已在1.9版本中移除,不再推荐使用

实现代码

ConcreteSubject.java

java">import java.util.Observable;// 目标对象
public class ConcreteSubject extends Observable {private String state;public void setState(String state) {this.state = state;// 表示目标对象已被改变setChanged();// 通知所有观察者notifyObservers();}public String getState() {return state;}
}

ObserverA.java

java">import java.util.Observable;
import java.util.Observer;/*** 观察者A** @author Anna.* @date 2024/4/25 16:15*/
public class ObserverA implements Observer {@Overridepublic void update(Observable o, Object arg) {System.out.printf("观察者A接收到消息-state:%s%n", ((ConcreteSubject) o).getState());}
}

ObserverB.java

java">import java.util.Observable;
import java.util.Observer;// 观察者B
public class ObserverB implements Observer {@Overridepublic void update(Observable o, Object arg) {System.out.printf("观察者B接收到消息-state:%s%n", ((ConcreteSubject) o).getState());}
}

TestClient.java

java">public class TestClient {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();subject.addObserver(new ObserverA());subject.addObserver(new ObserverB());subject.setState("STOP");}
}

执行结果:
在这里插入图片描述

案例3

通过拉方式,实现观察者主动拉取被观察者当前状态

UML

在这里插入图片描述

实现步骤:

  • 创建被观察者Subject,定义状态属性并提供get/set方法
  • 定义观察者接口类,提供拉取状态接口
  • 创建具体的观察者,实现观察者接口,通过持有被观察者的引用,主动拉取被观察者当前状态

实现代码

Subject.java

java">// 被观察者
public class Subject {// 定义当前状态private String state;public String getState() {return state;}public void setState(String state) {this.state = state;}
}

Observer.java

java">// 观察者接口
public interface Observer {// 定义拉取信息的接口void update();
}

ConcreteObserver.java

java">// 观察者具体实现
public class ConcreteObserver implements Observer {// 定义被观察者,持有被观察者的引用private Subject subject;public ConcreteObserver(Subject subject) {this.subject = subject;}@Overridepublic void update() {System.out.printf("观察者主动拉取状态-state:%s%n ", subject.getState());}
}

TestClient.java

java">public class TestClient {public static void main(String[] args) {// 创建被观察者Subject subject = new Subject();// 创建观察者ConcreteObserver observer = new ConcreteObserver(subject);// 修改状态subject.setState("RUN");// 观察者主动拉取observer.update();}
}

执行结果:

在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git


http://www.ppmy.cn/ops/16455.html

相关文章

平抑风电波动的电-氢混合储能容量优化配置

这篇论文中的EMD分解法在非线性扰动信号分解上优于小波分解法,EMD分解出来的imf各频次信号,继而利用C2F实现信号重构,根据最大波动量限值剔除出需要储能平抑的波动量,继而用超级电容实现平抑(论文中用的碱水电解槽+燃料电池我认为有很多个点可以佐证不合适,但是电制氢是热…

AIGC技术的发展现状和未来趋势

AIGC(AI-Generated Content)技术代表了人工智能发展的重要趋势,对各行各业都将产生革命性影响。总的来看,AIGC既蕴含着巨大的应用价值和发展机遇,但同时也带来一些值得关注的伦理风险和社会挑战。 从技术应用角度看,当前AIGC已经在多个领域崭露头角。在内容创作领域,GPT-3、DA…

Python:解析pyserial串口通讯

简介&#xff1a;串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方式的扩展接口。串行接口 &#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简单&#…

基于昇腾AI 使用AscendCL实现垃圾分类和视频物体分类应用

现如今&#xff0c;人工智能迅猛发展&#xff0c;AI赋能产业发展的速度正在加快&#xff0c;“AI”的需求蜂拥而来&#xff0c;但AI应用快速落地的过程中仍存在很大的挑战&#xff1a;向下需要适配的硬件&#xff0c;向上需要完善的技术支持&#xff0c;两者缺一不可。 基于此&…

6、ES单机设置用户名密码、集群设置用户名密码、es-head登录、如何去掉密码

目录 一、ES单节点密码配置1、修改配置文件2、 重启es服务3&#xff0c;执行修改密码命令4、访问服务 二、ES集群密码配置1、确定主节点2、生成elastic-stack-ca.p123、生成elastic-certificates.p124、修改配置文件并重启集群5、进行密码配置6、验证 三、es-head登录增加密码的…

C# 获取一个字符串中数字部分?

要在 C# 中将一个字符串中只保留数字字符&#xff0c;以下是两种实现方法&#xff1a; 方法一&#xff1a;使用正则表达式 正则表达式是一种强大的文本模式匹配工具&#xff0c;可以轻松地提取字符串中符合特定规则的部分。 在这种情况下&#xff0c;我们可以使用一个匹配数…

HTML

html初识 一、 学习html的目标&#xff1a;认识网页组成和五大浏览器&#xff0c;明确Web标准的构成。使用HTML骨架搭出一个网页。 认识网页。网页包括 &#xff1a;文字、图片、视频、音频、超链接。&#xff08;超链接指&#xff1a;点击文字或图片链接到其他的页面&#xf…

Spring Boot集成RabbitMQ快速入门Demo

1.什么是RabbitMQ&#xff1f; RabbitMQ是一款使用Erlang语言开发的&#xff0c;基于AMQP协议的消息中间件&#xff0c;作为一款优秀的消息系统&#xff0c;RabbitMQ有高并发、可扩展等优势&#xff0c;并适用于大型系统中各个模块之间的通信。 RabbitMQ的特点为&#xff1a; 持…