美文网首页编程语言-Java系列设计模式
[设计模式]事件监听器模式

[设计模式]事件监听器模式

作者: AbstractCulture | 来源:发表于2021-01-13 23:19 被阅读0次

回调函数

先从生活中的例子来理解这种过程:
我点了一份外卖,外卖到了外卖小哥会自动拨打我的电话通知我去拿外卖。
这个过程就是回调。

OK,这是一个simple的过程,那么用代码来实现如何实现。

实现一个简单的回调函数模型

  • UserOrder
package com.xjm.design.eventlistener.callback;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author jaymin<br>
 * 客户,负责点餐和留下联系方式<br>
 * 2021/1/10 21:16
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserOrder {
    /**
     * 食物名称
     */
    private String foodName;

    public UserOrder(DeliveryPerson deliveryPerson){
        deliveryPerson.supply(UserOrder.builder().foodName("冰红茶").build());
    }

    /**
     * 联系方式,配送员送到之后通过这个方法通知客户
     */
    public void callback(){
        System.out.println("食物已到达,请下楼取餐");
    }
}
  • DeliveryPerson
package com.xjm.design.eventlistener.callback;
/**
 * @author jaymin<br>
 * 配送员,负责按照客户的要求进行配送,配送完后通知客户进行用餐。<br>
 * 2021/1/10 21:17
 */
public class DeliveryPerson {

    public void supply(UserOrder userOrder){
        System.out.println("当前用户下单的食品清单:"+userOrder.getFoodName());
        System.out.println("到达商家拿到食物");
        System.out.println("抵达客户留下的地址,通知客户进行取餐");
        userOrder.callback();
    }
}
  • CallbackDemo
package com.xjm.design.eventlistener.callback;

/**
 * @author jaymin
 * 2021/1/10 21:34
 */
public class CallbackDemo {
    public static void main(String[] args) {
        UserOrder userOrder = new UserOrder(new DeliveryPerson());
    }
}
  • Result
Result

这样有什么坏处?硬编码了,不利于扩展.下面我们通过接口来实现多态.

重构回调函数

  • Callback
package com.xjm.design.eventlistener.callback;

/**
 * @author jaymin
 * 2021/1/10 21:41
 */
public interface Callback {

    void callback();

}
  • DeliveryPerson
package com.xjm.design.eventlistener.callback;

/**
 * @author jaymin<br>
 * 配送员,负责按照客户的要求进行配送,配送完后通知客户进行用餐。<br>
 * 2021/1/10 21:17
 */

public class DeliveryPerson {
    private String foodName;
    private Callback callback;


    public DeliveryPerson(Callback callback, String foodName) {
        this.callback = callback;
        this.foodName = foodName;
    }

    public void execute() {
        System.out.println("当前用户下单的食品清单:" + foodName);
        System.out.println("到达商家拿到食物");
        System.out.println("抵达客户留下的地址,通知客户进行取餐");
        callback.callback();
    }
}
  • CallbackDemo

这里使用lambda来代替内部类,写法上更加简洁.

package com.xjm.design.eventlistener.callback;

/**
 * @author jaymin
 * 2021/1/10 21:34
 */
public class CallbackDemo {
    public static void main(String[] args) {
        new DeliveryPerson(()-> System.out.println("食物已到达,请下楼取餐"),"冰红茶").execute();
    }
}

调用过程

callback

JDK中的回调函数-Runnable接口

Thread类中内置了一个private Runnable target;,在start的时候会回调Runnable接口的run方法.

        new Thread(()-> System.out.println("callback")).start();

扩展阅读

java 回调函数解读

事件监听器模式

由一组监听器订阅特定事件的发布,一旦该事件进行了发布,所有的监听器都会做出响应,其中的响应则是上文所述的回调函数.

事件监听器模式组成成员

  • 事件源: Event Source.被监听的对象,一旦事件源发生某个动作时,则调用其内置的事件监听器的方法,将事件对象进行广播.
  • 事件监听器: Event Listener. 监听事件源,可以对事件进行判断,进而响应.
  • 事件对象: Event Object.事件,通常为事件源广播的内容。
eventListener

代码示例

  • Event

定义事件发布的内容

package com.tea.design.eventlistener.pattern;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author jaymin<br>
 * 事件对象.<br>
 * 2021/1/11 22:10
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Event {

    private String message;

}
  • EventListener

定义事件监听器接口,声明处理事件的方法

package com.tea.design.eventlistener.pattern;

/**
 * @author jaymin<br>
 * 事件监听器<br>
 * 2021/1/11 22:18
 */
public interface EventListener {
    /**
     * 处理事件
     * @param event 事件
     */
    void processEvent(Event event);
}
  • OfflineNewsEventListener

监听事件进行日志打印

package com.tea.design.eventlistener.pattern;

import lombok.extern.slf4j.Slf4j;

/**
 * @author jaymin
 * 2021/1/11 22:28
 */
@Slf4j
public class OfflineNewsEventListener implements EventListener{
    @Override
    public void processEvent(Event event) {
        log.info("日报头条:今天大事件:{}",event.getMessage());
    }
}
  • OnlineNewsEventListener

监听事件进行日志打印

package com.tea.design.eventlistener.pattern;

import lombok.extern.slf4j.Slf4j;

/**
 * @author jaymin<br>
 * 如果发生大新闻,网络传媒要处理报道.<br>
 * 2021/1/11 22:27
 */
@Slf4j
public class OnlineNewsEventListener implements EventListener {
    @Override
    public void processEvent(Event event) {
        log.info("微博爆料:今天的爆炸新闻:{}", event.getMessage());
    }
}
  • EventSource

事件源,提供注册监听器方法与发布事件方法

package com.tea.design.eventlistener.pattern;

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

/**
 * @author jaymin
 * 2021/1/11 22:30
 */
public class EventSource {
    /**
     * 将所有的监听者进行存储
     */
    private List<EventListener> listenerList = new ArrayList<>();

    /**
     * 注册监听者
     * @param eventListener
     */
    public void addListener(EventListener eventListener){
        listenerList.add(eventListener);
    }

    /**
     * 发布事件
     * @param event
     */
    public void publishEvent(Event event){
        listenerList.forEach(eventListener -> eventListener.processEvent(event));
    }
}
  • EventListenerDemo
package com.tea.design.eventlistener.pattern;

/**
 * @author jaymin
 * 2021/1/11 22:33
 */
public class EventListenerDemo {
    public static void main(String[] args) {
        EventSource eventSource = new EventSource();
        OnlineNewsEventListener onlineNewsEventListener = new OnlineNewsEventListener();
        OfflineNewsEventListener offlineNewsEventListener = new OfflineNewsEventListener();
        eventSource.addListener(onlineNewsEventListener);
        eventSource.addListener(offlineNewsEventListener);
        eventSource.publishEvent(Event.builder().message("特朗普被推特永久封禁!").build());
    }
}
  • Result
result

总结

事件监听器模式与观察者模式大同小异,实现的思想是让被监听者/被观察者持有所有的监听器类,当需要是事件发布的时候,对这些监听器进行消息广播。
监听器实现至统一的接口,事件源会将事件对象作为参数进行传输,然后每个监听器处理自己对应的业务.
这体现了面向接口编程的设计原则,让代码耦合度更加松散。


缺点:

  • 多个监听器操作同一事件对象,监听器与监听器无法感知对方对该对象进行了什么操作。
  • 同步调用,如果部分监听器执行时间长,会增加耗时。可以采用异步处理的方式规避.

扩展阅读

  • JDK中的观察者模式
  • 消息队列的broker消费模式
  • Spring容器的事件监听器应用

相关文章

  • Java设计模式:事件驱动模式(观察者模式)

    Java设计模式——事件驱动模式(观察者模式) 角色 事件 事件源 事件监听器 事件 事件类一般继承自java.u...

  • java事件驱动模式(观察者模式)

    Java设计模式——事件驱动模式(观察者模式) 角色 事件 事件源 事件监听器 事件 事件类一般继承自java.u...

  • 2015年8月31日

    java设计模式--事件监听器模式和观察者模式 - 温水青蛙 - 博客频道 - CSDN.NET http://...

  • SpringBoot--监听器解析

    监听器模式 监听器模式有要素 事件 监听器 广播器 触发机制 系统监听器 监听器 ApplicationListe...

  • Java中的设计模式之适配器、模板设计模式

    今天咱们再来认识 两个设计模式 适配器设计模式 适配器 在使用监听器的时候, 需要定义一个类事件监听器接口。通常接...

  • [设计模式]事件监听器模式

    回调函数 先从生活中的例子来理解这种过程:我点了一份外卖,外卖到了外卖小哥会自动拨打我的电话通知我去拿外卖。这个过...

  • 异步编程解决方案

    事件发布/订阅模式 事件监听器模式是一种广泛用于异步编程的模式,是回调函数的事件化,又称发布/订阅模式。 事件发布...

  • SpringBoot源码分析之监听器

    1. spring监听器的设计 主要是基于发布订阅者设计模式,由广播器(MultiCaster)、事件(Event...

  • 事件驱动模型

    观察者模式与事件驱动模型 观察者模式: 事件驱动模型 2.事件驱动模型 事件源 持有监听器列表,或者各种类型监听器...

  • 设计模式之观察者模式

    观察者模式(常用设计模式) 观察者模式,是类的行为模式,又叫做发布订阅模式,模型视图模式,源监听器模式。 动机 将...

网友评论

    本文标题:[设计模式]事件监听器模式

    本文链接:https://www.haomeiwen.com/subject/xzcmaktx.html