为了看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")
;
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":"
www.baidu.com"}
ClickListener onEventAttach, event={"code":1,"source":{"id":"a_baidu","name":"跳转百度","value":"
www.baidu.com"}}
AllEventListener onEventAttach,event={"code":1,"source":{"id":"a_baidu","name":"跳转百度","value":"
www.baidu.com"}}
EventSource destory!
AllEventListener onEventAttach,event={"code":-1}