栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

事件中心与观察者模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

事件中心与观察者模式

事件中心与观察者模式
  • 楔子
  • 观察者模式
  • 事件中心demo
    • 被观察者
      • 具体的事件
    • 观察者
      • 具体事件的具体观察者
    • 主题
      • 具体的主题—>事件中心
    • 验证事件中心
  • 总结

楔子

event一种我们在代码中经常使用的对象。我们通过一定的方式创建出一个event,然后调用上下文将event发送出去。对应的listener就会收到消息并执行响应的逻辑。
我们都知道这种基于“事件”的开发中,用到设计模式就是观察者模式(也叫发布订阅模式),那么什么是观察者模式呢?

观察者模式

观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。

事件中心demo

在观察者模式中有三个要素:

  1. 主题,也就是我们的事件中心
  2. 观察者,众多listener
  3. 被观察的对象,各种event

好了,定义我们已经了解了,那么如何使用观察者模式实现一个事件中心呢?

被观察者

首先我们定一下被观察者,也就是我们的事件对象

public class baseEvent {

    private final Object data;

    public baseEvent(Object data) {
        this.data = data;
    }

    public Object getData() {
        return data;
    }
}
具体的事件

从事件基类中继承而来的一个具有业务场景的具体事件。

public class GetHomeEvent extends baseEvent {
    public GetHomeEvent(String userName) {
        super(userName);
    }
}
观察者

接下来我们定义一下观察者

public interface IEventListener {

    
    void listener(T event);
}
具体事件的具体观察者
public class AirCleanerGetHomeListener implements IEventListener {
    private static final Logger logger = LoggerFactory.getLogger(AirCleanerGetHomeListener.class);

    @Override
    public void listener(GetHomeEvent event) {
        logger.info("[{}]回来了,空气净化器已打开", event.getData());
    }
}

public class WifiGetHomeListener implements IEventListener {
    private static final Logger logger = LoggerFactory.getLogger(WifiGetHomeListener.class);

    @Override
    public void listener(GetHomeEvent event) {
        logger.info("WiFi已自动连接到[{}]的手机", event.getData());
    }
}
主题

主题,也就是我们的事件中心。事件中心有两大基本能力,注册和发布

public interface IEventCenter {

    
    void publishEvent(baseEvent event);

    
    void registerEvent(IEventListener eventListener);
}
具体的主题—>事件中心
public enum EventCenter implements IEventCenter {
    
    INSTANCE;

    private final Map> listenerMap = new HashMap<>();

    @Override
    public void publishEvent(baseEvent event) {
        //根据event的类型获取对应的listener
        List eventListeners = listenerMap.get(event.getClass());
        if (eventListeners != null) {
            eventListeners.forEach(eventListener -> eventListener.listener(event));
        }
        //如果发出的event不是baseEvent,那就给所有对baseEvent感兴趣的listener都发送一下消息
        if (!event.getClass().equals(baseEvent.class)) {
            List listeners = listenerMap.get(baseEvent.class);
            if (listeners != null) {
                listeners.forEach(eventListener -> eventListener.listener(event));
            }
        }
    }

    @Override
    public void registerEvent(IEventListener eventListener) {
        //建立起Listener感兴趣的Event类型与Listener的映射关系
        Class genericInterface = (Class) ((ParameterizedType) eventListener.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
        List eventListeners = listenerMap.computeIfAbsent(genericInterface, k -> new ArrayList<>());
        eventListeners.add(eventListener);
    }
}
验证事件中心
public class Main {
    private static final Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        IEventCenter eventCenter = EventCenter.INSTANCE;
        eventCenter.registerEvent(new AirCleanerGetHomeListener());
        eventCenter.registerEvent(new WifiGetHomeListener());
        //不指定具体的event类型,就是对所有事件都感兴趣
        eventCenter.registerEvent(new IEventListener() {
            @Override
            public void listener(baseEvent event) {
                logger.info("eventType[{}] getMessage [{}]", event.getClass().getSimpleName(), event.getData());
            }
        });
        eventCenter.publishEvent(new GetHomeEvent("张三"));
        eventCenter.publishEvent(new baseEvent("李四"));
    }
}

好了,我们看下结果:

22:47:49.464 [main] INFO com.example.designpatterns.observer.AirCleanerGetHomeListener - [张三]回来了,空气净化器已打开
22:47:49.464 [main] INFO com.example.designpatterns.observer.WifiGetHomeListener - WiFi已自动连接到[张三]的手机
22:47:49.464 [main] INFO com.example.designpatterns.observer.Main - eventType[GetHomeEvent] getMessage [张三]
22:47:49.464 [main] INFO com.example.designpatterns.observer.Main - eventType[baseEvent] getMessage [李四]

完全没有问题

总结
  1. 观察者模式定义了对象之间的一对多关系,比如在com.example.designpatterns.observer.EventCenter#listenerMap中存放了事件与监听器的一对多关系。
  2. 主题(也可能就是观察者)用一个共同的接口来更新观察者。就好像EventCenter调用com.example.designpatterns.observer.IEventListener#listener来触发事件一样。
  3. 当存在多个观察者时,不可以依赖特定的通知顺序。
  4. 面向接口开发,解耦利器。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/667100.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号