事件中心与观察者模式 您所在的位置:网站首页 我是一个观察者的英文 事件中心与观察者模式

事件中心与观察者模式

2024-06-03 13:32| 来源: 网络整理| 查看: 265

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

楔子

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

观察者模式

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

事件中心demo

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

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

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

被观察者

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

/** * 事件 * @author skyline */ public class BaseEvent { private final Object data; public BaseEvent(Object data) { this.data = data; } public Object getData() { return data; } } 具体的事件

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

/** * 到家了事件 * @author skyline */ public class GetHomeEvent extends BaseEvent { public GetHomeEvent(String userName) { super(userName); } } 观察者

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

/** * 事件监听者 * @author skyline */ public interface IEventListener { /** * 监听,当有事件到来时,这个方法会被调用 * @param event 事件 */ 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()); } } /** * wifi对回家监听 */ 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()); } } 主题

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

/** * 事件中心 * @author skyline */ public interface IEventCenter { /** * 发布事件 * @param event */ void publishEvent(BaseEvent event); /** * 注册事件 * @param eventListener */ void registerEvent(IEventListener eventListener); } 具体的主题—>事件中心 /** * 事件中心 * * @author skyline */ 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 [李四]

完全没有问题

总结 观察者模式定义了对象之间的一对多关系,比如在com.example.designpatterns.observer.EventCenter#listenerMap中存放了事件与监听器的一对多关系。主题(也可能就是观察者)用一个共同的接口来更新观察者。就好像EventCenter调用com.example.designpatterns.observer.IEventListener#listener来触发事件一样。当存在多个观察者时,不可以依赖特定的通知顺序。面向接口开发,解耦利器。


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有