IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 设计模式:观察者模式和监听器模式 -> 正文阅读

[Java知识库]设计模式:观察者模式和监听器模式

最近有个需求,大概是想用一下观察者模式/或者是监听器模式,来实现一下。那问题来了什么是观察者模式,什么是监听器模式?两者之间有哪些联系和不同。具体实现是什么样的,那就听我讲解一下。

观察者模式和监听器模式的组成

首先做一个总结,监听器模式实际上是在观察者模式的基础上进一步的封装。

首先是观察者模式,观察者模式分为两部分,观察者Observer和被观察者。观察者根据被观察者作为事件源,当执行逻辑涉及到触发逻辑,调用观察者的相关逻辑。

监听器相对来说多了个事件event,根据事件去监听。相当于是三部分EventSource事件源(有的地方也叫做register注册中心),Event事件(创建事件调动监听逻辑),Listener(监听器);

我这里借了一个别人的图:

在这里插入图片描述

观察者和监听器的具体实现

代码的地址我放在我的github上:

girhub:monitor和observer对应的实现,监听器那个模式由于是接口不是抽象类,可能有的idea会报错,但是可以执行,有时间我再修改一版

观察者:对应的是两部分Subject和Observer,一个是主体,观察者类似订阅者一样去订阅自己的主题。

被观察者或者说是主题的接口以及它的实现类

package com.example.test.observer;

import java.util.List;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 * @Desc:subject 被观察者(主题发布的主题)
 */
public interface Subject {

    /**
     * 添加观察者
     * @return
     */
    public List<Observer> addObserver(Observer observer);

    /**
     * 删除某个观察者
     * @param observer
     * @return
     */
//    public List<Observer> removeObserve(Observer observer);

    /**
     * 发送消息/主题,让观察者动起来
     */
    public void sendSubjectToObserver();


}

被观察者实现类

package com.example.test.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class SubjectImpl implements Subject{

    List<Observer> list;

    @Override
    public List<Observer> addObserver(Observer observer) {
        if(list == null){
            list = new ArrayList<>();
        }
        list.add(observer);
        return list;
    }

    @Override
    public void sendSubjectToObserver() {
         for(Observer observer : list){
              observer.sendSubject();
         }
    }
}

注意里面的几个方法,后面对比监听者也用的到。

观察者抽象类:之所以是抽象类是方便扩展实现不同类型的观察者

package com.example.test.observer;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public abstract class Observer {
    public abstract void sendSubject();
}

观察者A实例

package com.example.test.observer;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class ObserverA extends Observer{
    @Override
    public void sendSubject() {
        System.out.println("我是观察者A");
    }
}

我们观察一下观察者,觉得只分成两部分,能不能做个扩展对应触发观察者逻辑的部分能不能拿出来,这样迄不是扩展性更强。

当然可以监听器,就是单独出来一个事件,观察者根据事件的创建直接出发逻辑,看起来好像是在监听一样,听到消息就要去报告一样.

以下是监听器的代码

监听器的事件源,它对应的是观察者的被观察者的一部分,包括注册,维护观察者/监听器列表等。

package com.example.test.monitor;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 * 对比观察者的的被观察者/主题。这个角色进行对比
 */
public class EventSource {

    /**
     * 监听器列表
     */
    private List<MyMonitor> listeners;

    /**
     * 添加监听器
     * @param myMonitor
     * @return
     */
    public List<MyMonitor> addMonitor(MyMonitor myMonitor){
        if( listeners == null ){
            listeners = new ArrayList<>();
        }
        listeners.add(myMonitor);
        return listeners;
    }

    /**
     * 移除监听器
     * @return
     */
    public List<MyMonitor> removeMonitor(){
        if(listeners == null){
            return listeners;
        }
        for (MyMonitor listener : listeners){

            if(listeners.getClass().isInstance(DiguaMonitor.class)){
                listeners.remove(listener);
            }
            if(listener.getClass().isInstance(QieziMonitor.class)){
                listeners.remove(listener);
            }

        }
        return listeners;
    }


    public void gotoListener(Event event){
        for(MyMonitor listener : listeners){
            listener.monitotToTudou(event);
        }
    }
}

事件,其实可以看作是一个抽象出来的监视对象,当监视对象创建出来就会,有对应的监视器采取相关的动作,这里我用的是,“地瓜,地瓜,我是土豆,我听到了!”,这种耳熟能详的暗号来做例子,地瓜可以监视土豆,是不是茄子也可以,这是当然的。

以下是监视器的代码:

package com.example.test.monitor;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class DiguaMonitor implements MyMonitor{
    @Override
    public void monitotToTudou(Event event) {

       if(event.getType() == 1){
           System.out.println("地瓜,地瓜,我是土豆,我听到了!");
       }

    }
}

那现在我们缺一个被监视的土豆对象,这个被监视的对象就是我们的Event事件

package com.example.test.monitor;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class Event {

    /**
     * 类型:1 代表地瓜是监听者要监听的事件 ,2 代表茄子是监听者且子要监听的时间
     */
    private Integer type;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }
}

spring的监视器

spring也是自带监视器,不管是注解@EventListener还是实现ApplicationListener接口,实际都是你去继承实现人家定的模式。

当然他们刚开始是有区别的,有的是后置处理器处理的,有的是直接接口的实现类,但最后的去处都是spring的多播放器然后再到applicationListeners管理雕鹰在这里插入图片描述
这里面推荐一个小哥的专栏,我也是从这里对spring的两种监听器有了更深一步的了解。

涉及到spring的源码的spring监听器解析

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:02:36  更:2022-05-07 11:04:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:31:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码