zoukankan      html  css  js  c++  java
  • guava学习--事件驱动模型

    转载:http://www.cnblogs.com/whitewolf/p/4132840.html 

         http://www.cnblogs.com/peida/p/EventBus.html

    更好的文章:https://my.oschina.net/realfighter/blog/406342

    Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计。

    不再多的废话,直奔Guava EventBus主题。首先Guava为我们提供了同步事件EventBus和异步实现AsyncEventBus两个事件总线,他们都不是单例的,官方理由是并不想我们我们的使用方式。当然如果我们想其为单例,我们可以很容易封装它,一个单例模式保证只创建一个实例就对了。

    下面将以EventBus为例,AsyncEventBus使用方式与其一致的。

    1.同步事件EventBus

    订阅

    首先EventBus为我们提供了register方法来订阅事件,Guava在这里的实现很友好,我们不需要实现任何的额外接口或者base类,只需要在订阅方法上标注上@Subscribe和保证只有一个输入参数的方法就可以搞定。

    发布

    对于事件源,则可以通过post方法发布事件。 正在这里对于Guava对于事件的发布,是依据上例中订阅方法的方法参数类型决定的,换而言之就是post传入的类型和其基类类型可以收到此事件。

    建议对于每类事件封装一个特定的事件类型是必要的。

    消息封装类:

    public class TestEvent {
        private final int message;
        public TestEvent(int message) {        
            this.message = message;
            System.out.println("event message:"+message);
        }
        public int getMessage() {
            return message;
        }
    }

    消息接收类:

    public class EventListener {
        public int lastMessage = 0;
    
        @Subscribe
        public void listen(TestEvent event) {
            lastMessage = event.getMessage();
            System.out.println("Message:"+lastMessage);
        }
    
        public int getLastMessage() {      
            return lastMessage;
        }
    }

    测试类及输出结果:

    public class TestEventBus {
        @Test
        public void testReceiveEvent() throws Exception {
    
            EventBus eventBus = new EventBus("test");
            EventListener listener = new EventListener();
    
            eventBus.register(listener);
    
            eventBus.post(new TestEvent(200));
            eventBus.post(new TestEvent(300));
            eventBus.post(new TestEvent(400));
    
            System.out.println("LastMessage:"+listener.getLastMessage());
            ;
        }
    }
    
    //输出信息
    event message:200
    Message:200
    event message:300
    Message:300
    event message:400
    Message:400
    LastMessage:400
    
    

    MultiListener的使用:

      只需要在要订阅消息的方法上加上@Subscribe注解即可实现对多个消息的订阅,代码如下:

    public class MultipleListener {
        public Integer lastInteger;  
        public Long lastLong;  
       
        @Subscribe  
        public void listenInteger(Integer event) {  
            lastInteger = event; 
            System.out.println("event Integer:"+lastInteger);
        }  
       
        @Subscribe  
        public void listenLong(Long event) {  
            lastLong = event; 
            System.out.println("event Long:"+lastLong);
        }  
       
        public Integer getLastInteger() {  
            return lastInteger;  
        }  
       
        public Long getLastLong() {  
            return lastLong;  
        }  
    }

      测试类:

    public class TestMultipleEvents {
        @Test  
        public void testMultipleEvents() throws Exception {  
           
            EventBus eventBus = new EventBus("test");  
            MultipleListener multiListener = new MultipleListener();  
           
            eventBus.register(multiListener);  
           
            eventBus.post(new Integer(100));
            eventBus.post(new Integer(200));  
            eventBus.post(new Integer(300));  
            eventBus.post(new Long(800)); 
            eventBus.post(new Long(800990));  
            eventBus.post(new Long(800882934));  
           
            System.out.println("LastInteger:"+multiListener.getLastInteger());
            System.out.println("LastLong:"+multiListener.getLastLong());
        }   
    }
    
    //输出信息
    event Integer:100
    event Integer:200
    event Integer:300
    event Long:800
    event Long:800990
    event Long:800882934
    LastInteger:300
    LastLong:800882934

    在这里有 Integer,Long,与它们基类Number。我们发送一个整数数据的时候,或者Integer和Number的方法接收,而Long类型则Long类型和Number类型接受。
    可以使用此功能来创建更通用的监听器监听一个广泛的事件和更详细的具体的特殊的事件。(是类似的意思,看懂即可)。

    Dead Event:

      如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。实例如下:

    public class DeadEventListener {
        boolean notDelivered = false;  
           
        @Subscribe  
        public void listen(DeadEvent event) {  
            
            notDelivered = true;  
        }  
       
        public boolean isNotDelivered() {  
            return notDelivered;  
        }  
    }

      测试类:

    public class TestDeadEventListeners {
        @Test  
        public void testDeadEventListeners() throws Exception {  
           
            EventBus eventBus = new EventBus("test");               
            DeadEventListener deadEventListener = new DeadEventListener();  
            eventBus.register(deadEventListener);  
    
            eventBus.post(new TestEvent(200));         
            eventBus.post(new TestEvent(300));        
           
            System.out.println("deadEvent:"+deadEventListener.isNotDelivered());
    
        }  
    }
    
    //输出信息
    event message:200
    event message:300
    deadEvent:true

    说明:如果没有消息订阅者监听消息, EventBus将发送DeadEvent消息,这时我们可以通过log的方式来记录这种状态。

    更好的文章:https://my.oschina.net/realfighter/blog/406342
  • 相关阅读:
    Prometheus学习系列(九)之Prometheus 存储
    Prometheus学习系列(八)之Prometheus API说明
    SSE图像算法优化系列七:基于SSE实现的极速的矩形核腐蚀和膨胀(最大值和最小值)算法。
    Crimm Imageshop 2.3。
    【短道速滑一】OpenCV中cvResize函数使用双线性插值缩小图像到长宽大小一半时速度飞快(比最近邻还快)之异象解析和自我实现。
    【算法随记七】巧用SIMD指令实现急速的字节流按位反转算法。
    【算法随记六】一段Matlab版本的Total Variation(TV)去噪算法的C语言翻译。
    SSE图像算法优化系列三十:GIMP中的Noise Reduction算法原理及快速实现。
    一种快速简便优秀的全局曲线调整与局部信息想结合的非线性彩色增强算法(多图深度分析和探索)
    【算法随记五】使用FFT变换自动去除图像中严重的网纹。
  • 原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/6249385.html
Copyright © 2011-2022 走看看