- 楔子
- 观察者模式
- 事件中心demo
- 被观察者
- 具体的事件
- 观察者
- 具体事件的具体观察者
- 主题
- 具体的主题—>事件中心
- 验证事件中心
- 总结
event一种我们在代码中经常使用的对象。我们通过一定的方式创建出一个event,然后调用上下文将event发送出去。对应的listener就会收到消息并执行响应的逻辑。
我们都知道这种基于“事件”的开发中,用到设计模式就是观察者模式(也叫发布订阅模式),那么什么是观察者模式呢?
观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。
事件中心demo在观察者模式中有三个要素:
- 主题,也就是我们的事件中心
- 观察者,众多listener
- 被观察的对象,各种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 extends baseEvent> 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 extends baseEvent> 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来触发事件一样。
- 当存在多个观察者时,不可以依赖特定的通知顺序。
- 面向接口开发,解耦利器。



