Event-Driven架构设计消息处理系统

1. 需求

 基于Event-Driven架构设计实现如下需求
 *  1. 输入2个数 x 和 y, 并进行相加
 *  2. 对1中的结果进行格式化
 *  3. 将2中格式化的结果输出(打印)

2. 设计

使用Event-Driven架构进行设计,对于每一种消息类型分别定义 Event、Channel,进行差异化处理;

3. 代码逻辑

  • 接口Message, 每种消息实体实现Message接口(此处为Event);
  • 对于Event这种类型消息,定义子类 InputEvent、FormatEvent、ResultEvent对应于不同的阶段的实体;
  • 定义任务转发路由(Router)
  • 对于上述3中实体,分别对应不同的处理器(Channel);
  • 注册处理器

4. 代码

4.1 消息实体

package com.hz.design.eventdriven.message;

/**
 * @description: 消息接口
 * @author: pp_lan
 * @date: 2022/3/25
 */
public interface Message {

    /**
     * 返回消息类型
     * @return
     */
    Class getType();

}
package com.hz.design.eventdriven.message;

/**
 * @description: Event类型的消息
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class Event implements Message {

    @Override
    public Class getType() {
        return getClass();
    }
}
package com.hz.design.eventdriven.message;

/**
 * @description:
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class InputEvent extends Event {

    private final int x;
    private final int y;

    public InputEvent(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}
package com.hz.design.eventdriven.message;

/**
 * @description: 格式化事件
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class FormatEvent extends Event {

    private int result;

    public FormatEvent(int result) {
        this.result = result;
    }

    public int getResult() {
        return result;
    }
}
package com.hz.design.eventdriven.message;

/**
 * @description:
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class ResultEvent extends Event {

    private final String result;

    public ResultEvent(String result) {
        this.result = result;
    }

    public String getResult() {
        return result;
    }
}

4.2 任务转发Router

package com.hz.design.eventdriven.router;

import com.hz.design.eventdriven.channel.Channel;
import com.hz.design.eventdriven.message.Message;

/**
 * @description: 动态路由
 * @author: pp_lan
 * @date: 2022/3/25
 */
public interface DynamicRouter {

    /**
     * 每种类型的消息注册一个通道
     *
     * @param messageType
     * @param channel
     */
    void registerChannel(Class messageType, Channel channel);

    /**
     * 调度:为Channel分配Message
     *
     * @param message
     */
    void dispatch(E message);

}
package com.hz.design.eventdriven.router;

import com.hz.design.eventdriven.channel.Channel;
import com.hz.design.eventdriven.message.Event;
import com.hz.design.eventdriven.message.Message;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description: 调度器
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class EventDispatcher implements DynamicRouter {

    private final Map, Channel> routerTable;

    public EventDispatcher() {
        this.routerTable = new ConcurrentHashMap<>();
    }

    @Override
    public void registerChannel(Class messageType, Channel channel) {
        this.routerTable.put(messageType, channel);
    }

    /**
     * 分发: 根据Event的类型获取对应的处理器(Channel)。如: InputEvent--> InputEventHandler, resultEvent --> ResultEventHandler
     * @param message
     */
    @Override
    public void dispatch(Event message) {

        if (this.routerTable.containsKey(message.getType())) {
            System.out.format("事件转发: %s\n", message.getType().getSimpleName());
            routerTable.get(message.getType()).dispatch(message);
        } else {
            throw new RuntimeException(String.format("该类型的消息未注册:%s", message.getType()));
        }
    }
}

4.3 处理器Channel

package com.hz.design.eventdriven.channel;

import com.hz.design.eventdriven.message.Message;

/**
 * @description: 通道
 * @author: pp_lan
 * @date: 2022/3/25
 */
public interface Channel {

    /**
     * 调度消息
     *
     * @param message
     */
    void dispatch(E message);
}
package com.hz.design.eventdriven.channel;

import com.hz.design.eventdriven.message.FormatEvent;
import com.hz.design.eventdriven.message.InputEvent;
import com.hz.design.eventdriven.message.ResultEvent;
import com.hz.design.eventdriven.router.EventDispatcher;

/**
 * @description:
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class InputEventHandler implements Channel {

    private final EventDispatcher resultDispatcher;

    public InputEventHandler(EventDispatcher resultDispatcher) {
        this.resultDispatcher = resultDispatcher;
    }

    @Override
    public void dispatch(InputEvent message) {

        // 输入后进行计算
        int result = message.getX() + message.getY();
        System.out.printf("input结果:%d\n", result);

        // 将消息交给结果处理器
        resultDispatcher.dispatch(new FormatEvent(result));
    }
}
package com.hz.design.eventdriven.channel;

import com.hz.design.eventdriven.message.Event;
import com.hz.design.eventdriven.message.FormatEvent;
import com.hz.design.eventdriven.message.ResultEvent;
import com.hz.design.eventdriven.router.EventDispatcher;

/**
 * @description:
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class FormatEventHandler implements Channel {

    private final EventDispatcher dispatcher;

    public FormatEventHandler(EventDispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

    @Override
    public void dispatch(FormatEvent message) {

        int result = message.getResult();

        String resultFormat = String.format("【格式化】标准输出结果为: %d", result);
        System.out.printf("format结果:%s\n", resultFormat);

        this.dispatcher.dispatch(new ResultEvent(resultFormat));
    }
}
package com.hz.design.eventdriven.channel;

import com.hz.design.eventdriven.message.ResultEvent;

/**
 * @description:
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class ResultEventHandler implements Channel {

    @Override
    public void dispatch(ResultEvent message) {
        System.out.format("result结果: %s\n", message.getResult());
    }
}

4.4 测试类

package com.hz.design.eventdriven;

import com.hz.design.eventdriven.channel.FormatEventHandler;
import com.hz.design.eventdriven.channel.InputEventHandler;
import com.hz.design.eventdriven.channel.ResultEventHandler;
import com.hz.design.eventdriven.message.FormatEvent;
import com.hz.design.eventdriven.message.InputEvent;
import com.hz.design.eventdriven.message.ResultEvent;
import com.hz.design.eventdriven.router.EventDispatcher;

/**
 * @description: 基于Event-Driven架构设计实现如下需求
 *  1. 输入2个数 x 和 y, 并进行相加
 *  2. 对1中的结果进行格式化
 *  3. 将2中格式化的结果输出(打印)
 * @author: pp_lan
 * @date: 2022/3/25
 */
public class EventDispatcherTest {

    public static void main(String[] args) {

        EventDispatcher dispatcher = new EventDispatcher();


        // 注册事件(Event)对应的处理器: InputEvent --> InputEventHandler, ResultEvent --> ResultEventHandler
        dispatcher.registerChannel(InputEvent.class, new InputEventHandler(dispatcher));

        // 格式化数据事件
        dispatcher.registerChannel(FormatEvent.class, new FormatEventHandler(dispatcher));

        // ResultEventHandler为最后一个结果,不再需要dispatcher进行转发了
        dispatcher.registerChannel(ResultEvent.class, new ResultEventHandler());

        dispatcher.dispatch(new InputEvent(2, 5));
    }
}

5. 执行结果

Connected to the target VM, address: '127.0.0.1:62897', transport: 'socket'
事件转发: InputEvent
input结果:7
事件转发: FormatEvent
format结果:【格式化】标准输出结果为: 7
事件转发: ResultEvent
result结果: 【格式化】标准输出结果为: 7
Disconnected from the target VM, address: '127.0.0.1:62897', transport: 'socket'

参考:《JAVA高并发编程详解》-汪文君

你可能感兴趣的:(设计模式,设计模式,java)