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
时间: 2024-10-17 14:07:16

guava学习--事件驱动模型的相关文章

Guava ---- EventBus事件驱动模型

在软件开发过程中, 难免有信息的共享或者对象间的协作. 怎样让对象间信息共享高效, 而且耦合性低. 这是一个难题. 而耦合性高将带来编码改动牵一发而动全身的连锁效应. Spring的风靡正是由于攻克了高耦合问题. 本篇介绍的EventBus中也用到了Spring中的依赖注入. 来进行对象和对象间的解耦(如@Subscribe). Guava解决高耦合採用的是事件驱动模型的思路. 对象能够订阅(subscribe)特定的事件或者公布(publish)特定的事件去被消费. 从以下的代码能够看出, E

让开发效率爆表的Guava ---- EventBus事件驱动模型

在软件开发过程中, 难免有信息的共享或者对象间的协作. 如何让对象间信息共享高效, 并且耦合性低, 这是一个难题. 而耦合性高将带来编码修改牵一发而动全身的连锁效应, Spring的风靡正是因为解决了高耦合问题. 本篇介绍的EventBus中也用到了Spring中的依赖注入, 来进行对象和对象间的解耦(如@Subscribe). Guava解决高耦合采用的是事件驱动模型的思路, 对象可以订阅(subscribe)特定的事件或者发布(publish)特定的事件去被消费. 从下面的代码可以看出, E

事件驱动模型Libev(二)

Libev设计思路 理清了Libev的代码结构和主要的数据结构,就可以跟着示例中接口进入到Libev中,跟着代码了解其设计的思路.这里我们管struct ev_loop称作为事件循环驱动器而将各种watcher称为事件监控器. 1.分析例子中的IO事件 这里在前面的例子中我们先把定时器和信号事件的使用注释掉,只看IO事件监控器,从而了解Libev最基本的逻辑.可以结合Gdb设断点一步一步的跟看看代码的逻辑是怎样的. 我们从main开始一步步走.首先执行 struct ev_loop *main_

由Node.js事件驱动模型引发的思考

引言 近段时间听说了Node.js,很多文章表述这个事件驱动模型多么多么优秀,应用在服务器开发中有很大的优势,本身对此十分感性去,决定深入了解一下,由此也引发了一些对程序设计的思考,记录下来. 什么是Node.js Node.js在官网上是这样定义的:"一个搭建在Chrome JavaScript运行时上的平台,用于构建高速.可伸缩的网络程序.Node.js采用的事件驱动.非阻塞I/O模型使它既轻量又高效,是构建运行在分布式设备上的数据密集型实时程序的完美选择." Node.js的事件

跟我学android之四 事件驱动模型

Android事件驱动模型需要深刻学习和理解,事件驱动模型三要素如下: 事件驱动模型 事件源:事件的制造者,如:按钮 通常会拥有注册和取消监听器的功能 监听器:事件的接收者,通常是自己编写的类的对象 一个实现了事件源所支持的事件接口的类 事件:事件源产生的某一个具体事件 一个事件源可以产生多种事件 一个监听器可以接收多个事件 事件的处理程序通常位于监听器内部 事件驱动模型 工作步骤 1.定义监听器,为每一个事件编写处理方法 2.将监听器对象注册给事件源 3.事件源发生某个事件时调用监听器中对应的

事件驱动模型。。。。有时间弄

public class A{ private Vector aListeners = new Vector(); private int value; public int getValue(){ return value; } public void setValue(int newValue){ if(value!=newValue){ value = newValue; AEvent evt= new AEvent(this,value); //如果值改变的话,就触发事件 fireAEv

观察者模式实现事件驱动模型(非GUI事件)

先引入四人帮之书里面关于观察者模式的一段高度概括 观察者模式-- 定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并自动更新. 事件驱动模型是观察者模式的一种典型应用.该模式主要由事件源,事件对象,以及事件监听器三元素构成.以常见的点击事件为例子.按钮为事件源,相当于观察者模式中的被观察者;点击为事件对象;事件监听器,相当于观察者模式中的观察者.当事件源的属性发生变化时,所有监听该事件的事件监听器都会接收到消息并作出响应. 关于"事件"这种抽象,

(六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型)决了当时的问题,那时LZ接触JAVA刚几个月,比葫芦画瓢的用了观察者模式。

本章我们讨论一个除前面的单例以及代理模式之外,一个WEB项目中有可能用到的设计模式,即观察者模式. 说起观察者模式,LZ还是非常激动的,当初这算是第一个让LZ感受到设计模式强大的家伙.当初LZ要做一个小型WEB项目,要上传给服务器文件,一个需求就是要显示上传进度,LZ就是用这个模式解决了当时的问题,那时LZ接触JAVA刚几个月,比葫芦画瓢的用了观察者模式. 现在谈及观察者模式,能用到的地方就相对较多了,通常意义上如果一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式.

事件驱动模型实例详解(Java篇)

或许每个软件从业者都有从学习控制台应用程序到学习可视化编程的转变过程,控制台应用程序的优点在于可以方便的练习某个语言的语法和开发习惯(如.net和java),而可视化编程的学习又可以非常方便开发出各类人机对话界面(HMI).可视化编程或许是一个初学者开始对软件感兴趣的开始,也可能是一个软件学习的里程碑点,因为我们可以使用各类软件集成开发环境(IDE)方便的在现成的界面窗口上拖放各类组件(Component),这类组件包括我们常见的按钮(Button),单选按钮(Radio Button),复选框