返回顶部
首页 > 资讯 > 前端开发 > VUE >如何实现观察者模式及Spring中的事件编程模型
  • 117
分享到

如何实现观察者模式及Spring中的事件编程模型

2024-04-02 19:04:59 117人浏览 泡泡鱼
摘要

这篇“如何实现观察者模式及spring中的事件编程模型”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来

这篇“如何实现观察者模式及spring中的事件编程模型”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何实现观察者模式及Spring中的事件编程模型”文章吧。

  什么是观察者模式

  在现实生活中,观察者模式处处可见,比如

  看新闻,只要新闻开始播放了,就会把新闻推送给订阅了新闻的用户,在这里,新闻就是【被观察者】,而用户就是【观察者】。

  微信公众号,如果一个用户订阅了某个公众号,那么便会收到公众号发来的消息,那么,公众号就是【被观察者】,而用户就是【观察者】。

  热水器,假设热水器由三部分组成,热水器,警报器,显示器,热水器仅仅负责烧水,当水温到达设定的温度后,通知警报器,警报器发出警报,显示器也需要订阅热水器的烧水事件,从而获得水温,并显示。热水器就是【被观察者】,警报器,显示器就是【观察者】。

  在这里,可以看到,【观察者】已经失去自主的权利,只能被动的接收来自【被观察者】的事件,无法主动观察。【观察者】成为了“受”,而【被观察者】成为了“攻”。【被观察者】只是通知【观察者】,不关心【观察者】收到通知后,会执行怎样的动作。

  而在设计模式中,又把【被观察者】称为【主题】。

  在观察者设计模式中,一般有四个角色:

  抽象主题角色(Subject)

  具体主题角色(ConcreteSubject)

  抽象观察者角色(Observer)

  具体观察者角色(ConcreteObserver)

  其中,【主题】需要有一个列表字段,用来保存【观察者】的引用,提供两个方法(虚方法),即【删除观察者】【增加观察者】,还需要提供一个给客户端调用的方法,通知各个【观察者】:你们关心(订阅)的事件已经推送给你们了。

  下面,我就用三种方式来实现观察者模式。

  经典

  public class News {

  private String title;

  private String content;

  public String getTitle() {

  return title;

  }

  public void setTitle(String title) {

  this.title = title;

  }

  public String getContent() {

  return content;

  }

  public void setContent(String content) {

  this.content = content;

  }

  }

  此类不属于观察者模式必须的类,用来存放事件的信息。

  public interface Subject {

  List<People> peopleList = new ArrayList<>();

  default void add(People people) {

  peopleList.add(people);

  }

  default void remove(People people) {

  peopleList.remove(people);

  }

  void update();

  }

  抽象主题角色,在这个角色中,有一个字段peopleList,用来保存【观察者】的引用,同时定义了两个接口,这是Java8默认接口实现的写法。这两个接口是给客户端调用的,用来【删除观察者】【增加观察者】,还提供一个方法,此方法需要被【具体主题角色】重写,用来通知各个【观察者】。

  public class NewsSubject implements Subject{

  public void update() {

  for (People people : peopleList) {

  News news = new News();

  news.setContent("今日在大街上,有人躲在草丛中袭击路人,还大喊“德玛西亚万岁”");

  news.setTitle("德玛西亚出现了");

  people.update(news);

  }

  }

  }

  具体主题角色,重写了【抽象主题角色】的方法,循环列表,通知各个【观察者】。

  public interface People {

  void update(News news);

  }

  抽象观察者角色,定义了一个接口,【具体观察者角色】需要重写这个方法。

  下面就是【具体观察者角色】了:

  public class PeopleA implements People {

  @Override

  public void update(News news) {

  System.out.println("这个新闻真好看");

  }

  }

  public class PeopleB implements People {

  @Override

  public void update(News news) {

  System.out.println("这个新闻真无语");

  }

  }

  public class PeopleC implements People {

  @Override

  public void update(News news) {

  System.out.println("这个新闻真逗");

  }

  }

  客户端:

  public class Main {

  public static void main(String[] args) {

  Subject subject = new NewsSubject();

  subject.add(new PeopleA());

  subject.add(new PeopleB());

  subject.add(new PeopleC());

  subject.update();

  }

  }

  运行:

  我们学习设计模式,必须知道设计模式的优缺点,那么观察者设计模式的优缺点是什么呢?

  优点:

  【主题】和【观察者】通过抽象,建立了一个松耦合的关系,【主题】只知道当前有哪些【观察者】,并且发送通知,但是不知道【观察者】具体会执行怎样的动作。这也很好理解,比如 微信公众号推送了一个消息过来,它不知道你会采取如何的动作,是 微笑的打开,还是愤怒的打开,或者是直接把消息删了,又或者把手机扔到洗衣机洗刷刷。

  符合开闭原则,如果需要新增一个【观察者】,只需要写一个类去实现【抽象观察者角色】即可,不需要改动原来的代码。

  缺点:

  客户端必须知道所有的【观察者】,并且进行【增加观察者】和【删除观察者】的操作。

  如果有很多【观察者】,那么所有的【观察者】收到通知,可能需要花费很久时间。

  当然以上优缺点,是最直观的,可以很容易理解,并且体会到的。其他优缺点,可以自行百度。

  Lambda

  在介绍这种写法之前,有必要介绍下函数式接口,函数式接口的概念由来已久,一般来说只定义了一个虚方法的接口就叫函数式接口,在Java8中,由于Lambda表达式的出现,让函数式接口大放异彩。

  我们仅仅需要修改客户端的代码就可以:

  public static void main(String[] args) {

  Subject subject = new NewsSubject();

  subject.add(a -> System.out.println("已阅这新闻"));

  subject.add(a -> System.out.println("假的吧"));

  subject.add(a -> System.out.println("昨天就看过了"));

  subject.update();

  }

  运行结果:

  利用Lambda表达式和函数式接口,可以省去【具体观察者角色】的定义,但是个人认为,这并非属于严格意义上的观察者模式,而且弊端很明显:

  客户端需要知道观察者的具体实现。

  如果观察者的具体实现比较复杂,可能代码并没有那么清晰。

  所以这种写法,具有一定的局限性。

  借用大神的一句话

  设计模式的出现,是为了弥补语言的缺陷。

  正是由于语言的升级,让某些设计模式发生了一定的变化,除了观察者模式,还有模板方法模式、责任链模式等,都由于 Lambda表达式的出现,而出现了一些变化。

  jdk

  在Java中,本身就提供了一个接口:Observer,一个子类:Observable,其中Observer表示【观察者】,Observable表示【主题】,可以利用这两个子类和接口来实现观察者模式:

  public class NewsObservable extends Observable {

  public void update() {

  setChanged();

  notifyObservers();

  }

  }

  public class People1 implements Observer {

  @Override

  public void update(Observable o, Object arg) {

  System.out.println("小编真无聊");

  }

  }

  public class People2 implements Observer {

  @Override

  public void update(Observable o, Object arg) {

  System.out.println("开局一张图,内容全靠编");

  }

  }

  客户端:

  public static void main(String[] args) {

  NewsObservable newsObservable = new NewsObservable();

  newsObservable.addObserver(new People1());

  newsObservable.addObserver(new People2());

  newsObservable.update();

  }

  运行结果:

  在这里,我不打算详细介绍这种实现方式,因为从Java9开始,Java已经不推荐这种写法了,而推荐用消息队列来实现。是不是很开心,找到一个借口不去研究Observable,Observer 这两个东西了。

  Spring中的事件编程模型

  Spring中的事件编程模型就是观察者模式的实现,SpringBoot就利用了Spring的事件编程模型来完成一些操作,这里暂时不表。

  在Spring中定义了一个ApplicationListener接口,从名字就知道它是一个监听器,是监听Application的事件的,那么Application又是什么,就是ApplicationContext,ApplicationContext内置了几个事件,其中比较容易理解的是:

  ContextRefreshedEvent

  ContextStartedEvent

  ContextStoppedEvent

  ContextClosedEvent

  从名称上来看,就知道这几个事件是什么时候被触发的了。

  下面我演示下具体的用法,比如我想监听ContextRefreshedEvent事件,如果事件发生了,就打印一句话。

  @Component

  public class MyListener implements ApplicationListener{

  @Override

  public void onApplicationEvent(ApplicationEvent applicationEvent) {

  if(applicationEvent  instanceof ContextRefreshedEvent){

  System.out.println("刷新了");

  }

  }

  }

  @Configuration

  @ComponentScan

  public class AppConfig {

  }

  public static void main(String[] args) {

  AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);

  }

  运行结果:

  当时学习Spring,看到Spring提供了各式各样的接口来让程序员们对Spring进行扩展,并且没有任何侵入性,我不得不佩服Spring的开发者们。这里也是,我们可以看到在客户端找不到任何关于“订阅事件”的影子。

  这种实现方式不是太好,可以看到我们在方法内部做了一个判断:接收到的事件是否为ContextRefreshedEvent。

  伟大的Spring还提供了泛型的ApplicationListener,我们可以通过泛型的ApplicationListener来完善上面的代码:

  @Component

  public class MyListener implements ApplicationListener<ContextRefreshedEvent> {

  @Override

  public void onApplicationEvent(ContextRefreshedEvent event) {

  System.out.println("刷新了");

  }

  }

  我们还可以利用Spring中的事件编程模型来自定义事件,并且发布事件:

  首先,我们需要定义一个事件,来实现ApplicationEvent接口,代表这是一个Application事件,其实上面所说的四个内置的事件也实现了ApplicationEvent接口:

  public class MyEvent extends ApplicationEvent {

  public MyEvent(Object source) {

  super(source);

  }

  }

  还需要定义一个监听器,当然,在这里需要监听MyEvent事件:

  @Component

  public class MyListener implements ApplicationListener<MyEvent> {

  @Override

  public void onApplicationEvent(MyEvent event) {

  System.out.println("我订阅的事件已经到达");

  }

  }

  现在有了事件,也有了监听器,是不是还少了发布者,不然谁去发布事件呢?

  @Component

  public class MyEventPublish implements ApplicationEventPublisherAware {

  private ApplicationEventPublisher publisher;

  @Override

  public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

  this.publisher = applicationEventPublisher;

  }

  public void publish(Object obj) {

  this.publisher.publishEvent(obj);

  }

  }

  发布者,需要实现ApplicationEventPublisherAware 接口,重写publish方法,顾名思义,这就是发布方法,那么方法的参数obj是干嘛的呢,作为发布者,应该需要知道我要发布什么事件,以及事件来源(是谁触发的)把,这个obj就是用来存放这样的数据的,当然,这个参数需要我们手动传入进去。setApplicationEventPublisher是Spring内部主动调用的,可以简单的理解为初始化发布者。

  现在就剩最后一个角色了,监听器有了,发布者有了,事件也有了,对,没错,还少一个触发者,毕竟要有触发者去触发事件啊:

  @Component

  public class Service {

  @Autowired

  private  MyEventPublish publish;

  public void publish() {

  publish.publish(new MyEvent(this));

  }

  }

  其中publish方法就是给客户端调用的,用来触发事件,可以很清楚的看到传入了new MyEvent(this),这样发布者就可以知道我要触发什么事件和是谁触发了事件。

  当然,还需要把一切交给Spring管理:

  @Configuration

  @ComponentScan

  public class AppConfig {

  }

  客户端:

  public static void main(String[] args) {

  AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);

  context.getBean(Service.class)。publish();;

  }

以上就是关于“如何实现观察者模式及Spring中的事件编程模型”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网VUE频道。

--结束END--

本文标题: 如何实现观察者模式及Spring中的事件编程模型

本文链接: https://lsjlt.com/news/93657.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何实现观察者模式及Spring中的事件编程模型
    这篇“如何实现观察者模式及Spring中的事件编程模型”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来...
    99+
    2024-04-02
  • Javascript中如何实现观察者模式
    本篇文章为大家展示了Javascript中如何实现观察者模式,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。基础知识观察者模式定义了对象间的一种一对多依赖关系,每当一...
    99+
    2024-04-02
  • php如何实现观察者模式
    这篇文章主要介绍了php如何实现观察者模式,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。php实现观察者模式的方法:首先创建一个PHP示例文件;然后实现观察者向主题注册;最后...
    99+
    2023-06-14
  • 如何使用PHP实现观察者模式
    小编给大家分享一下如何使用PHP实现观察者模式,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!观察者模式为您提供了避免组件之间紧密...
    99+
    2024-04-02
  • Java编程中的观察者模式是什么
    这篇文章主要介绍“Java编程中的观察者模式是什么”,在日常操作中,相信很多人在Java编程中的观察者模式是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java编程中的观察者模式是什么”的疑惑有所帮助!...
    99+
    2023-05-30
    java
  • vue中怎么实现观察者模式
    vue中怎么实现观察者模式,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1 响应式原理让我们先从相应式原理开始。我们可以通过O...
    99+
    2024-04-02
  • vue如何用组件传值实现观察者模式
    这篇文章主要介绍“vue如何用组件传值实现观察者模式”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue如何用组件传值实现观察者模式”文章能帮助大家解决问题。第一步,我们先在main.js中注册一下...
    99+
    2023-07-04
  • JavaScript设计模式中的观察者模式怎么实现
    本文小编为大家详细介绍“JavaScript设计模式中的观察者模式怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“JavaScript设计模式中的观察者模式怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-07-02
  • PHP中的观察者模式如何工作?
    php 中的观察者模式是一种设计模式,允许观察者订阅主题的状态变化并做出响应。当主题状态更改时,它会通知观察者,观察者可以相应地更新自己:主题类维护一个观察者列表并提供方法附加和删除观察...
    99+
    2024-05-21
    php 观察者模式
  • C#中的EventHandler观察者模式怎么实现
    这篇文章主要介绍“C#中的EventHandler观察者模式怎么实现”,在日常操作中,相信很多人在C#中的EventHandler观察者模式怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#中的Eve...
    99+
    2023-06-29
  • JAVA观察者模式的的讲解及代码实现
    目录概念组成 实现 总结 概念 观察者模式又叫做发布-订阅模式,是对象间的一对多的关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动...
    99+
    2024-04-02
  • JavaScript观察者模式:掌控事件流,实现数据同步
    1. JavaScript观察者模式概述 JavaScript观察者模式是一种设计模式,它允许对象订阅并响应其他对象的事件。这种模式非常适合用于管理事件流和实现数据同步。在观察者模式中,有一个被观察者对象(Subject)和多个观察者对...
    99+
    2024-02-03
    JavaScript 观察者模式 事件流 数据同步
  • Java实现数据更新和事件通知的观察者模式
    目录介绍实现总结优点缺点应用场景介绍 Java观察者模式(也称发布-订阅模式)是一种行为设计模式,用于对象之间的松散耦合,即当一个对象的状态发生变化时,其他依赖该对象的对象会被自动通...
    99+
    2023-05-17
    Java观察者模式 Java设计模式
  • JS中自定义事件与观察者模式详解
    目录一、前言二、观察者模式优缺点三、代码实现四、DOM自定义事件API一、前言 观察者模式 也称发布-订阅模式 、 模型-视图模式 。当对象间存在一对多关系时,则使用观察者模式(Ob...
    99+
    2024-04-02
  • java和Spring中观察者模式的应用详解
    目录一、观察者模式基本概况1.概念2.作用3.实现方式二、java实现两种观察者模式1.Observer接口和Observable类2.EventObject和EventListen...
    99+
    2024-04-02
  • JS中自定义事件与观察者模式实例分析
    这篇文章主要介绍了JS中自定义事件与观察者模式实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JS中自定义事件与观察者模式实例分析文章都会有所收获,下面我们一起来看看吧。一、前言观察者模式 也称发布-订阅...
    99+
    2023-07-02
  • 举例讲解Python设计模式编程中的访问者与观察者模式
    访问者模式 我觉得Visitor模式是在补修改已有程序结构前提下,通过添加额外的访问者完成对代码功能的拓展 为什么这样用?当你的类层次较多,在某层结构中增加新的方法,要是在基类上面添加或者变更,可能破坏原来...
    99+
    2022-06-04
    模式 观察者 访问者
  • JavaScript观察者模式:用事件串联应用程序组件
    一、什么是观察者模式 观察者模式是一种设计模式,它允许对象通过事件来通信。在观察者模式中,有一个被观察者对象(又称为发布者对象)和多个观察者对象(又称为订阅者对象)。被观察者对象负责发布事件,而观察者对象负责订阅这些事件并作出相应的反应。...
    99+
    2024-02-03
    JavaScript 观察者模式 事件 松散耦合 应用程序组件
  • 详解Python设计模式编程中观察者模式与策略模式的运用
    观察者模式 观察者模式:又叫发布订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时,会通知所有观察者对象,是他们能自动更新自己。 代码结构 cla...
    99+
    2022-06-04
    模式 观察者 详解
  • java实现观察者模式的示例分析
    小编给大家分享一下java实现观察者模式的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则...
    99+
    2023-05-30
    java
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作