java实现观察者模式

为了看netty源码做准备。


观察者模式、发布-订阅模型、reactor模式本质上类似,通过事件回调来解耦动作执行者和观察者。
观察者模式中主要分三个角色:
  1. 观察者(监听器)
  2. 事件(执行的动作)
  3. 事件源(监视对象)

具体的实现方式分两步:
  1. 观察者初始化,绑定到事件源
  2. 事件发生时通知绑定了该事件的观察者

代码如下:
  1. 观察者:
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)) ;
    }
}
  1. 事件对象
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 ;}
}
  1. 事件源
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)) ;
        }
    }
}
  1. 演示代码
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" , "跳转百度" , " www.baidu.com ") ;
        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}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值