图片.png

前言

了解设计模式的童鞋应该都知道观察者模式,类似于上图的结构,其中Observer作为观察者,Observable则作为被观察者,Observable的状态改变会给注册的Observer进行通知,考虑易用和低耦合,保证高度的协作。

Demo展示

我们首先来看一下demo,也就是上图类图中所展示的程序,MyObservable非常简单,只是继承了Observable:

public class MyObservable extends Observable{

public static void main(String[] args) {

MyObservable myObservable = new MyObservable();

myObservable.addObserver(new MyObserver());

myObservable.setChanged();

myObservable.notifyObservers("aaa");

}

}

此处为了简化结构,直接将main方法写在MyObservable中用于进行效果的测试,main中我们先实例化了MyObservable类,并且将一个MyObserver实例用addObserver方法加入它的观察者列表中,然后通过setChanged改变changed的状态值,随后便可以notifyObservers,里面可以带参数做消息传递,也可以不带参数。关于changed,是因为只有该变量为true的情况下,才会进行通知,否则notifyObservers是无法通知到具体Observer的。

MyObserver的结构也非常简单,由于继承了Observer接口,因此需要实现它的抽象方法update,这个方法也是用于接收Observable发来的通知并执行相应的处理逻辑的:

public class MyObserver implements Observer{

public void update(Observable o, Object arg) {

System.out.println("观察对象为:" + o + ";传递参数为:" + arg);

}

}

运行一下demo,可以看到结果为:

观察对象为:com.sunny.MyObservable@60e53b93;传递参数为:aaa

而在注释了setChanged方法之后,会发现没有任何输出,可以理解为,并没有真正通知到Observer。

原理解析

原理非常简单,查看Observable源码即可。其实从类图中就可以看出一些端倪,Observable中只有两个变量,一个是changed,一个是obs,从之前的分析可以看出changed只是一个状态指示的变量,那么obs应该就是一个用于存储Observer实例的变量了,它具体是用一个Vector来进行存储的。

private boolean changed = false;

private Vector obs;

这样的情况下,我们很容易就可以猜测,obs的初始化应该是在Observable的构造方法中实现的,果不其然,构造方法也仅仅只是完成了obs的初始化:

public Observable() {

obs = new Vector<>();

}

然后我们更为关心的是Observable与Observer之间的关系,那么就是重点关注两个方法,addObserver和notifyObservers。addObserver很显然,里面的主要操作是将作为参数传入的Observer加入到Vector中:

public synchronized void addObserver(Observer o) {

if (o == null)

throw new NullPointerException();

if (!obs.contains(o)) {

obs.addElement(o);

}

}

notifyObservers则是逐一通知Observer的过程,不过在这个方法中会检查changed的值,以及会在通知完成后对changed归零(其中clearChanged方法就是将changed变量重新置为false):

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);

}

到这里基本上整个基于jdk实现的观察者模式的原理已经非常明了了,另外值得注意的一个点是,这个实现中用了一些措施来使它线程安全。比如,使用线程安全的容器Vector,addObserver方法进行了枷锁,在notifyObservers方法中,有一个操作进行了加锁:

synchronized (this) {

if (!changed)

return;

arrLocal = obs.toArray();

clearChanged();

}

这里主要确保了对changed变量的验证和清零操作以及将obs中的元素赋值给arrLocal的过程是原子操作,这里减少了锁的粒度,提高并发性,也因此大家能明白为何需要arrLocal这个变量了,随后对arrLocal数组进行便利并逐一通知则不需要加锁了,因为arrLocal已经是一个本地变量,并未暴露。

综上,就是基于jdk实现观察者模式的主要原理了。

欢迎小伙伴与我讨论哦~

java与模式观察者模式_谈谈java中的观察者模式相关推荐

  1. java timmer模式配置_使用java配置定时任务的几种配置方式及示例

    Spring定时器,主要有两种实现方式,包括Java Timer定时和Quartz定时器! 1.Java Timer定时 首先继承java.util.TimerTask类实现run方法 package ...

  2. java.lang.IllegalArgumentException: 字符[_]在域名中永远无效。 at

    [http-nio-8080-exec-1] org.apache.coyote.AbstractProcessor.parseHost [xxx_tomcat] 是无效主机注意:更多的请求解析错误将 ...

  3. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  4. java观察者模式在spring中的应用_在Spring中使用观察者模式

    菜鸟教程中关于观察者模式的介绍如下: 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而 ...

  5. java 观察者模式_图解Java设计模式之观察者模式

    图解Java设计模式之观察者模式 天气预报项目需求 天气预报设计方案 1 - 普通方案 观察者模式(Observer)原理 观察者模式解决天气预报需求 观察者模式在JDK应用的源码分析 天气预报项目需 ...

  6. java多核并行计算_谈谈Java任务的并行处理

    前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分利用cpu资源:如果站的更高 ...

  7. java stream 求和_谈谈Java任务的并行处理

    作者:ksfzhaohui 前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分 ...

  8. java web.xml 监听器_【JAVA 核心技术】java web 中的监听器

    为什么要有监听器? 监听器是用来处理一系列事件的java类,可被配置在java web项目中. 既然如此,为什么不用代码直接调用监听器? 这可能是因为J2EE规范规定的项目工程标准,用web.xml指 ...

  9. java使用外部库_在Java中使用外部库

    java使用外部库 Java附带了一组核心库,其中包括定义常用数据类型和相关行为的库,例如String或Date : 与主机操作系统进行交互的实用程序,例如System或File : 有用的子系统来管 ...

  10. java与模式孙悟空_悟空模式-java-工厂方法模式

    [却说那七衣仙女自受了大圣的定身法术,一周天方能解脱,各提花篮,回奏王母说道:"齐天大圣使术法困住我等,故此来迟."王母问道:"汝等摘了多少蟠桃?"仙女道:&q ...

最新文章

  1. 利用TCMalloc替换Nginx和Redis默认glibc库的malloc内存分配
  2. 从键盘输入一个正整数(不多于5位),计算该正整数与789之和(记为sum)
  3. Jass 技能模型定义(转)
  4. 不装mono,你的.NET程序照样可以在Linux上运行
  5. java 去掉 t_关于Java:在LocalDateTime中不能删除“ T”
  6. 华为云EI人脸识别接口初探
  7. 饮冰三年-人工智能-Python-27 Django Form组件
  8. twaver html5,twaver-html5-1.5.9---2D
  9. 满满的提高芝麻分实操技巧!
  10. KATEX公式编辑器符号大全-CSDN的Mardown公式支持
  11. 鸡小德手机小常识 如何鉴定手机是否为行货
  12. Flutter 3更新详解
  13. 【交互设计师必备书单】资深交互设计师推荐的交互设计师必看的七本书
  14. python pip安装numpy_【风马一族_Python】 安装pip与Numpy
  15. oracle 数据库如何获取一条sql语句执行所消耗耗费的时间?
  16. 解决VS在Release下编译程序报“应用程序无法启动,应用程序的并行配置不正确”的问题
  17. 思维升级-如何设计一个秒杀系统?
  18. 2022年广电行业研究报告
  19. C++黑客编程:键盘记录器,HOOK技术实现
  20. Linux下的cmt2300a驱动

热门文章

  1. trycatch抛出异常_满屏的trycatch,这代码写得真丑!
  2. bio和bieos哪个标注模式好_通用块层bio详解
  3. cpu顶盖怎么看步进_拆解报告|360AI音箱,深度硬件解析,带你看懂360智能音箱内部...
  4. JavaScript:判断两个日期之间的差距天数
  5. HighCharts:设置坐标轴字体样式
  6. Git:git commit后撤销commit 提交
  7. 实战爬虫:python爬虫之爬取虎扑湖人专区新闻中科比相关新闻
  8. 论文笔记_S2D.71_2020_CVPR_用于自监督单目深度估计的3D packing
  9. Ubuntu安装Tensorflow及anaconda环境下使用TensorFlow
  10. mysql 数据库授权