java实现观察者模式
发布日期:2021-06-28 19:59:38
浏览次数:2
分类:技术文章
本文共 3672 字,大约阅读时间需要 12 分钟。
为了看netty源码做准备。
观察者模式、发布-订阅模型、reactor模式本质上类似,通过事件回调来解耦动作执行者和观察者。
观察者模式中主要分三个角色:
- 观察者(监听器)
- 事件(执行的动作)
- 事件源(监视对象)
具体的实现方式分两步:
- 观察者初始化,绑定到事件源
- 事件发生时通知绑定了该事件的观察者
代码如下:
- 观察者:
public interface Listener {
void onEventAttach(Event event) ;
}
两个实现:AllEventListener和ClickListener
public class AllEventListener implements Listener {
@Override
public void onEventAttach(Event event) {
System. out.println( "AllEventListener onEventAttach,event=" + JSON. toJSONString(event)) ;
}
}
public class ClickListener implements Listener {
@Override
public void onEventAttach(Event event) {
System. out.println( "ClickListener onEventAttach, event=" + JSON. toJSONString(event)) ;
}
}
- 事件对象
public class Event {
public static final int INIT = 0 ;
public static final int CLICK = 1 ;
public static final int DESTORY = - 1 ;
private int code ;
private Object data ;
public Event( int code , Object data) {
this. code = code ;
this. data = data ;
}
public int getCode() { return code ;}
public Object getData() { return data ;}
}
- 事件源
import com.alibaba.fastjson.JSON ;
import java.util.* ;
public class EventSource {
public final Object BIND_LOCK = new Object() ;
public Map<Integer , Set<Listener>> eventListenerMap = new HashMap<>() ;
public void bind(Listener listener , int eventCode) {
synchronized ( BIND_LOCK) {//这个lock可以优化
Set<Listener> listenerSet = eventListenerMap.get(eventCode) ;
if (listenerSet == null || listenerSet.isEmpty()) {
listenerSet = new HashSet<>() ;
}
listenerSet.add(listener) ;
eventListenerMap.put(eventCode , listenerSet) ;
}
}
public void bind(Listener listener , List<Integer> eventCodeList) {
eventCodeList.forEach(eventCode -> bind( listener , eventCode)) ;
}
public EventSource() {
System. out.println( "EventSource create!") ;
}
public void init() {
System. out.println( "EventSource init!") ;
notifyListener(Event. INIT , null) ;
}
public void click(Element element) {// element自己新建一个bean,或者改成Map/Object即可
System. out.println( "EventSource click!element=" + JSON. toJSONString(element)) ;
notifyListener(Event. CLICK , element) ;
}
public void destory() {
System. out.println( "EventSource destory!") ;
notifyListener(Event. DESTORY , null) ;
}
private void notifyListener( int eventCode , Object data) {
Set<Listener> listenerSet = eventListenerMap.get(eventCode) ;
if (listenerSet != null && !listenerSet.isEmpty()) {
Event event = new Event(eventCode , data) ;
listenerSet.forEach(listener -> listener.onEventAttach( event)) ;
}
}
}
- 演示代码
public class Demo {
public static void main(String[] args) {
EventSource source = new EventSource() ;
Element element1 = new Element( "btn_query" , "查询" , "查询1") ;
Element element2 = new Element( "a_baidu" , "跳转百度" , " ") ;
Listener all = new AllEventListener() ;
Listener clickListener = new ClickListener() ;
source.bind(clickListener , Event. CLICK) ;
source.bind(all , Arrays. asList(Event. INIT , Event. CLICK , Event. DESTORY)) ;
source.init() ;
source.click(element1) ;
source.click(element2) ;
source.destory() ;
}
}
输出如下:
EventSource create!
EventSource init!
AllEventListener onEventAttach,event={"code":0}
EventSource click!element={"id":"btn_query","name":"查询","value":"查询1"}
ClickListener onEventAttach, event={"code":1,"source":{"id":"btn_query","name":"查询","value":"查询1"}}
AllEventListener onEventAttach,event={"code":1,"source":{"id":"btn_query","name":"查询","value":"查询1"}}
EventSource click!element={"id":"a_baidu","name":"跳转百度","value":" "}
ClickListener onEventAttach, event={"code":1,"source":{"id":"a_baidu","name":"跳转百度","value":" "}}
AllEventListener onEventAttach,event={"code":1,"source":{"id":"a_baidu","name":"跳转百度","value":" "}}
EventSource destory!
AllEventListener onEventAttach,event={"code":-1}
转载地址:https://blog.csdn.net/xxxxssss12/article/details/79311425 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
不错!
[***.144.177.141]2024年04月15日 23时54分59秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Linux常用基础命令198个
2019-04-29
Linux运维工程师初级面试题
2019-04-29
GA入门
2019-04-29
kettle问题合集
2019-04-29
spark学习笔记
2019-04-29
Tableau学习笔记
2019-04-29
Kettle学习笔记
2019-04-29
airflow问题合集
2019-04-29
sql
2019-04-29
BI分析
2019-04-29
springboot+mybatis+sharding-jdbc整合分库分表实战
2019-04-29
linux查看文件命令介绍
2019-04-29
Spring bean作用域介绍
2019-04-29
Spring 组件开发利器Aware接口
2019-04-29
Spring bean初始化方法的几种写法
2019-04-29
Spring @Autowired注解使用总结
2019-04-29
Spring bean的生命周期总结
2019-04-29
DCL实现单例要不要加volatile修饰
2019-04-29
Spring源码日志分析
2019-04-29
Spring 自定义标签的使用
2019-04-29