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

行为设计模式 -观察者模式- JAVA

观察者模式

    • 一.简介
    • 二. 案例
      • 2.1 抽象主题(Subject)
      • 2.2 具体主题(Concrete Subject)
      • 2.3 抽象观察者(Observer)
      • 2.4 具体观察者(Concrete Observer)
      • 2.5 测试
    • 三. 结论
      • 3.1 优缺点
      • 3.2 使用场景

前言

这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一.简介

百度百科: 观察者模式是一种对象行为模式。又被称为发布-订阅(Publish/Subscribe)模式, 它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互、权限管理等方面也有广泛的应用。

个人理解: 这个模式在日常开发中很常见,比如a服务想要b服务磁盘满的时候通知它,那么它只需要把自己的grpc或者http接口给到b服务,b服务订阅后,如果磁盘满了就调用a服务注册的接口 通知。

在观察者模式中有如下角色:

  • 抽象主题(Subject) 它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  • 具体主题(Concrete Subject): 将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  • 抽象观察者(Observer): 为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  • 具体观察者(Concrete Observer): 实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

二. 案例

我将实现一个简单的主题(Subject)观察者(Observer)可以注册到该主题。每当有新消息发布到主题时,所有注册观察者都会收到通知,并且他们可以使用该消息。

请添加图片描述

这里是基本Subject接口,它定义了任何具体主题要实现的接口方法。

2.1 抽象主题(Subject)

/*** @author chenyunzhi* @date 2024/6/5 17:13* @Description 主题*/
public interface Subject {/*** 注册观察者*/void register(Observer observer);/*** 取消观察者*/void unregister(Observer observer);/*** 通知观察者消息有更新*/void notifyObservers();}

2.2 具体主题(Concrete Subject)

/*** @author chenyunzhi* @date 2024/6/5 17:21* @Description 实现主题*/
public class SubjectImpl implements Subject{/*** 同步锁*/private final Object SUB= new Object();/*** 存储注册的观察者*/private final List<Observer> observers = new ArrayList<>();/*** 要通知的消息*/private String message;/*** 防止 notifyObservers方法被外部调用发送错误通知*/private boolean flag;@Overridepublic void register(Observer observer) {if (observer != null) {synchronized (SUB) {// 如果不在就存储if (!observers.contains(observer)) {observers.add(observer);}}}}@Overridepublic void unregister(Observer observer) {if (observer != null) {synchronized (SUB) {observers.remove(observer);}}}@Overridepublic void notifyObservers() {List<Observer> objects = new ArrayList<>();//使用同步方法确保通知仅发送给新消息前注册的观察者synchronized (SUB) {if (!flag) {return;}objects = this.observers;this.flag = false;}for (Observer observer:objects) {// 通知观察者,有消息更新observer.update(this.message);}}/*** 自定义一个消息变更方法方便测试*/public void updateMessage(String message) {System.out.println("消息有变更,通知注册的观察者");this.message = message;this.flag = true;// 通知notifyObservers();}
}

2.3 抽象观察者(Observer)

/*** @author chenyunzhi* @date 2024/6/5 17:14* @Description 观察者类*/
public interface Observer {/*** 定义要更新的方法,由主题调用*/void update(String msg);
}

2.4 具体观察者(Concrete Observer)

/*** @author chenyunzhi* @date 2024/6/5 17:59* @Description 观察者实现类*/
public class ObserverImpl implements Observer{/*** 观察者名称*/private final String observerName;public ObserverImpl(String name) {this.observerName = name;}@Overridepublic void update(String msg) {System.out.println(observerName + "接收到消息:" + msg);}
}

2.5 测试

/*** @author chenyunzhi* @date 2024/6/6 14:57* @Description 观察者模式测试*/
public class ObserverPatternTest {public static void main(String[] args) {// 创建观察者并注册到主题SubjectImpl subject = new SubjectImpl();subject.register(new ObserverImpl("观察者1"));subject.register(new ObserverImpl("观察者2"));subject.register(new ObserverImpl("观察者3"));// 测试 更新消息subject.updateMessage("订阅的主题有消息更新了");}
}

请添加图片描述

三. 结论

3.1 优缺点

1.优点:

  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  • 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】

2.缺点:

  • 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
  • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃

3.2 使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。


http://www.mrgr.cn/news/42166.html

相关文章:

  • PDF转PPT:四款热门工具的亲身体验分享!
  • 搭建k8s集群服务(kubeadm方式)
  • 2019~2023博文汇总目录
  • MISC -第十天(音符加解密、敲击码、NtfsStreamsEditor工具)
  • SpringCloud Config配置中心 SpringCloud Bus消息总线
  • 【web安全】——文件包含漏洞
  • some 蓝桥杯题
  • (六)Shell 脚本应用(1):基础与环境变量详解
  • Linux驱动开发(速记版)--设备树插件
  • Linux命令:用于显示 Linux 发行版信息的命令行工具lsb_release详解
  • JAVA思维提升案例2
  • 总结一下 KNN、K-means 和 SVM【附代码实现】
  • 杀疯啦!yolov11+strongsort的目标跟踪实现
  • 华为OD机试 - 密室逃生游戏(Python/JS/C/C++ 2024 E卷 100分)
  • 更美观的HTTP性能监测工具:httpstat
  • 【自然语言处理】(1) --语言转换方法
  • 小错误(输入数据)牛客 14683 储物点的距离
  • Oracle中MONTHS_BETWEEN()函数详解
  • 【笔记】选择题笔记408
  • PADS自动导出Gerber文件 —— 6层板