Event Driven 模式详解与一个设计实现 | Java

本文深入探讨了Event Driven事件驱动模式,包括消息通信模式,如发布/订阅、点对点和请求/响应。文章还介绍了如何在Java中实现Event Driven模式,引用了Reactor模式,并提供了基于 Vert.X 架构的设计灵感。通过测试用例和详细的接口、类设计,展示了Acceptor、Dispatcher、EventBus等关键组件的实现。
摘要由CSDN通过智能技术生成

昨天想写个Event Driven模式,看了不少资料也成功写出了一个实现,先简单说下,以后细聊

Event Driven 事件驱动模式

  • Event Bus 模式 传递消息的,复杂的是在主机间传递
  • Event Driven 模式 处理消息的,通常与 Event Bus 工作在一起,复杂的是实现消息通信模式
  • Reactor 模式 同 Event Driven 模式,只是关注 IO 事件

消息通信模式

  • 发布/订阅 模式 消息被发布到一个address/topic,也就是说派发消息到所有注册在这个address/topic 的处理器去处理
  • 点对点 模式 同上,不过消息只被派发到一个处理器上
  • 请求/响应 模式 同点对点,不过处理器还能回一个消息给消息生产者,生产者能接受到这个消息

更多资料

代码

测试

代码命名和设计真的参考了Vert.X很多,先给一段测试结果

        // 接口的静态工厂方法,总是返回同一个单例实现
        EventBus eventBus = EventBus.bus();


        AtomicInteger id = new AtomicInteger(1);

        // 调用 eventbus api 来常见消费者,或者叫处理器
        eventBus.<String>consumer("comment.post", msg -> {
   
            System.out.println("消费者-1: 【消息已持久化到数据库】" + msg);
        });

        eventBus.<String>consumer("comment.post", msg -> {
   
            System.out.println("消费者-2: 【你有一条新回复】" + msg.data());
        });

        // 通过返回的 MessageConsumer 引用,方便注销这个消费者
        var c3 =  eventBus.<Integer>consumer("comment.notify", msg -> {
   
            System.out.println("消费者-3: 【点赞通知】已获得 " + msg.data() + " 个赞");
        });

        // 构建两个消息/事件生产者
        MessageProducer<String> producer1 = eventBus.producer("comment.post");
        MessageProducer<Integer> producer2 = eventBus.producer("comment.notify");

        // 模拟一个事件/消息流
        IntStream.range(1, 501).forEach( i -> {
   
            producer1.write("已三连,谢谢UP主 #" + id.getAndIncrement());
            producer2.write(i);
        });

        // 通过 eventbus 直接发消息
        eventBus.<String>send("comment.post", "最后一层了!");

        // 注销消费者/处理器
        // c3.unregister();

接口和类设计

Acceptor.java
package com.onemsg.plan.eda;

/**
 * Acceptor 事件/消息 接收者
 */
public interface Acceptor {
   

    /**
     * 开启事件循环
     */
    void startEventLoop();
    
    /**
     * 接受一个消息
     */
    void accept(Message<Object> event);

    /**
     * 关闭
     */
    void close();
}
Dispatcher.java
package com.onemsg.plan.eda;

import java.util.Set;

/**
 * 事件/消息 调度者
 */
public interface Dispatcher {
   
    
    /**
     * 派发一个事件给对应的处理器
     * @param event 事件
     */
    void dispatch(Message<Object> event);

    /**
     * 所有的消息地址/主题
     * @return 消息地址集合
     */
    Set<String> addresses();

    /**
     * 返回在指定消息地址注册的处理器集合
     * @param address
     * @return 处理器集合
     */
    Set<MessageConsumer<Object>> consumeres(String address);

    /**
     * 注册新的事件消费者
     * @param consumer
     * @return true/false 表示成功或失败
     */
    boolean addRegistration(MessageConsumer<Object> consumer);

    /**
     * 注销一个事件消费者
     * @param <T>
     * @param consumer
     * @return true/false 是否注销成功
     */
    <T> boolean removeRegistration(MessageConsumer<T> consumer);

    void close();
}
EventBus.java
package com.onemsg.plan.eda;

import java.util.Map;

import com.onemsg.plan.eda.impl.EventBusImpl;

/**
 * <p>事件总线</p>
 * <p>一般作为主要的用户使用接口</p>
 */
public interface EventBus {
   
    
    /**
     * 向指定地址添加新的事件处理器,返回一个新的事件消费者
     * @param <T>
     * @param address
     * @param handler
     * @return 事件消费者
     */
    <T> MessageConsumer<T> consumer(String address, Handler<Message<T>> handler);
    
    /**
     * 返回给定地址的新的时间消费者
     * @param <T> 数据类型
     * @param address
     * @return 事件消费者
     */
    <T> MessageConsumer<T> consumer(String address);
    
    /**
     * 向给定地址发送事件,包含数据
     * @param <T> 数据类型
     * @param address
     * @param data 要发送的数据
     */
    <T> void send(String address, T data);
    
    /**
     * 像给定地址发送事件,包含数据和消息头
     * @param <T> 数据类型
     * @param address
     * @param data 要发送的数据
     * @param headers 消息头
     */
    <T> void send(String address, T data, Map<String, String> headers);
    
    /**
     * 发送一个事件,地址和数据不能为空,否则抛出异常
     * @param <T> 数据类型
     * @param event 事件
     */
    <T> void send(Message<T> event) throws NullPointerException;
    
    /**
     * 返回给定地址的消息成产值
     * @param <T>
     * @param address
     * @return
     */
    <T> MessageProducer<T> producer(String address);

    void close();

    /**
     * 返回一个单例 EventBus
     */
    static EventBus bus(){
   
        return EventBusImpl.instance();
    }
}
Handler.java
package com.onemsg.plan.eda;

/** 
 * 事件/消息 处理器
 * <p>这是一个函数式接口</p>
 */
@FunctionalInterface
public interface Handler<E> {
   
    
    void handle(E event);
}
Message.java
package com.onemsg.plan.eda;

import java.util.Map;

/**
 * 事件/消息
 * @param <T> 数据类型
 */
public interface Message<T> {
   
    
    /**
     * @return 地址
     */
    String address();

    /**
     * @return 消息头
     */
    Map<String,String> headers(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值