在软件开发过程中, 难免有信息的共享或者对象间的协作。 怎样让对象间信息共享高效, 而且耦合性低。 这是一个难题。 而耦合性高将带来编码改动牵一发而动全身的连锁效应。 Spring的风靡正是由于攻克了高耦合问题。 本篇介绍的EventBus中也用到了Spring中的依赖注入。 来进行对象和对象间的解耦(如@Subscribe)。

Guava解决高耦合採用的是事件驱动模型的思路。 对象能够订阅(subscribe)特定的事件或者公布(publish)特定的事件去被消费。 从以下的代码能够看出, EventBus对生产者和消费者是透明的, 它无需知道他们的类型。 从而实现了解耦。

TradeAccountEvent: 基本对象兼測试类

package com.wenniuwuren.eventbus;
import com.google.common.eventbus.EventBus; import java.util.Date; /**
* 无论什么时候买卖交易运行, 都会产生一个TradeAccountEvent实例
*/
public class TradeAccountEvent {
private double amount;
private Date tradeExecutionTime;
private String tradeType;
private String tradeAccount; public TradeAccountEvent(String account, double amount,
Date tradeExecutionTime, String tradeType) {
this.amount = amount;
this.tradeExecutionTime =tradeExecutionTime;
this.tradeAccount = account;
this.tradeType = tradeType;
} public static void main(String[] args) {
// 消费者和生产者依据EventBus对象来一一相应
EventBus eventBus1 = new EventBus();
SimpleTradeAuditor simpleTradeAuditor = new SimpleTradeAuditor(eventBus1);
SimpleTradeExecutor simpleTradeExecutor = new SimpleTradeExecutor(eventBus1);
simpleTradeExecutor.executeTrade("zhangsan", 10, "Money"); System.out.println("----This is devil dividing line------"); EventBus eventBus2 = new EventBus();
BuySellTradeExecutor buySellTradeExecutor = new BuySellTradeExecutor(eventBus2);
AllTradesAuditor allTradesAuditor = new AllTradesAuditor(eventBus2);
buySellTradeExecutor.executeTrade("lisi", 100, "SELL");
System.out.println("---------------------");
buySellTradeExecutor.executeTrade("wangwu", 1000, "BUY");
}
}

AllTradesAuditor:依据不同生产者订阅不同内容

package com.wenniuwuren.eventbus;

import java.util.List;

import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe; public class AllTradesAuditor {
private List<BuyEvent> buyEvents = Lists.newArrayList();
private List<SellEvent> sellEvents = Lists.newArrayList(); public AllTradesAuditor(EventBus eventBus) {
eventBus.register(this);
} @Subscribe
public void auditSell(SellEvent sellEvent) {
sellEvents.add(sellEvent);
System.out.println("Received TradeSellEvent " + sellEvent);
} @Subscribe
public void auditBuy(BuyEvent buyEvent) {
buyEvents.add(buyEvent);
System.out.println("Received TradeBuyEvent " + buyEvent);
}
}

BuyEvent:

package com.wenniuwuren.eventbus;

import java.util.Date;

/**
* 购买事件
* @author wenniuwuren
*
*/
public class BuyEvent extends TradeAccountEvent {
public BuyEvent(String tradeAccount, double amount,
Date tradExecutionTime) {
super(tradeAccount, amount, tradExecutionTime, "BUY");
}
}

SellEvent:

package com.wenniuwuren.eventbus;

import java.util.Date;

/**
* 销售事件
* @author wenniuwuren
*
*/
public class SellEvent extends TradeAccountEvent {
public SellEvent(String tradeAccount, double amount, Date tradExecutionTime) {
super(tradeAccount, amount, tradExecutionTime, "SELL");
}
}

BuySellTradeExecutor: 分类型(BUY、SELL)公布事件

package com.wenniuwuren.eventbus;

import java.util.Date;

import com.google.common.eventbus.EventBus;

/**
* 分类型(SELL BUY)运行器
* @author wenniuwuren
*
*/ public class BuySellTradeExecutor { private EventBus eventBus; public BuySellTradeExecutor(EventBus eventBus) { this.eventBus = eventBus;
} private TradeAccountEvent processTrade(String tradeAccount, double amount,
String tradeType) {
Date executionTime = new Date();
String message = String.format("Processed trade for" + tradeAccount
+ "of amount" + amount + "type" + tradeType + "@"
+ executionTime);
TradeAccountEvent tradeAccountEvent;
if (tradeType.equals("BUY")) {
tradeAccountEvent = new BuyEvent(tradeAccount, amount,
executionTime);
} else {
tradeAccountEvent = new SellEvent(tradeAccount, amount,
executionTime);
}
System.out.println(message);
return tradeAccountEvent;
} public void executeTrade(String tradeAccount, double amount, String tradeType) {
TradeAccountEvent tradeAccountEvent = processTrade(tradeAccount, amount, tradeType);
// 公布, 通知订阅者
eventBus.post(tradeAccountEvent);
}
}

SimpleTradeAuditor: 最简单的事件消费者(或者说订阅者)

package com.wenniuwuren.eventbus;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe; import java.util.List; /**
* 审核交易
*/
public class SimpleTradeAuditor {
private List<TradeAccountEvent> tradeEvents = Lists.newArrayList(); public SimpleTradeAuditor(EventBus eventBus) {
// 注冊, 以便获取TradeAccountEvent的通知
eventBus.register(this);
} /**
* 事件处理(用@Subscribe注解表示)
* @param tradeAccountEvent
*/
@Subscribe
public void auditTrade(TradeAccountEvent tradeAccountEvent) {
tradeEvents.add(tradeAccountEvent);
System.out.println("Received trade " + tradeAccountEvent);
}
}

TradeBuyAuditor:分类型事件消费

package com.wenniuwuren.eventbus;

import java.util.List;

import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe; /**
* 购买审查
* @author wenniuwuren
*
*/
public class TradeBuyAuditor {
private List<BuyEvent> buyEvents = Lists.newArrayList(); public TradeBuyAuditor(EventBus eventBus) {
eventBus.register(this);
} @Subscribe
public void auditBuy(BuyEvent buyEvent) {
buyEvents.add(buyEvent);
System.out.println("Received TradeBuyEvent " + buyEvent);
} public List<BuyEvent> getBuyEvents() {
return buyEvents;
}
}

TradeSellAuditor:

package com.wenniuwuren.eventbus;

import java.util.List;

import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe; /**
* 销售审查
* @author wenniuwuren
*
*/
public class TradeSellAuditor {
private List<SellEvent> sellEvents = Lists.newArrayList(); public TradeSellAuditor(EventBus eventBus) {
eventBus.register(this);
} @Subscribe
public void auditSell(SellEvent sellEvent) {
sellEvents.add(sellEvent);
System.out.println("Received SellEvent " + sellEvent);
} public List<SellEvent> getSellEvents() {
return sellEvents;
}
}

输出结果:

Processed trade forzhangsanof amount10.0typeMoney@Fri Jun 12 02:29:03 CST 2015
Received trade com.wenniuwuren.eventbus.TradeAccountEvent@7c53a9eb
----This is devil dividing line------
Processed trade forlisiof amount100.0typeSELL@Fri Jun 12 02:29:03 CST 2015
Received TradeSellEvent com.wenniuwuren.eventbus.SellEvent@14899482
---------------------
Processed trade forwangwuof amount1000.0typeBUY@Fri Jun 12 02:29:03 CST 2015
Received TradeBuyEvent com.wenniuwuren.eventbus.BuyEvent@21588809

參考资料:

《Getting Started with Google Guava》

Guava ---- EventBus事件驱动模型的更多相关文章

  1. guava学习--事件驱动模型

    转载:http://www.cnblogs.com/whitewolf/p/4132840.html   http://www.cnblogs.com/peida/p/EventBus.html 更好 ...

  2. Guava - EventBus(事件总线)

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

  3. (六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 本章我们讨论一个除前面的单例 ...

  4. Python自动化之select、greenlet和gevent和事件驱动模型初探

    进程.线程和协程的区别 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度. 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的). 协程和线程一样 ...

  5. 详解Spring事件驱动模型

    转载自:http://jinnianshilongnian.iteye.com/blog/1902886#comments 事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型:理 ...

  6. 设计模式:Observer(观察者)—— Guava EventBus

    本文分为三个部分:   Observer(观察者) Guava EventBus详解 Guava EventBus使用示例   1. Observer(观察者)   1.1 背景   我们设计系统时, ...

  7. Java学习疑惑(8)----可视化编程, 对Java中事件驱动模型的理解

    我们编写程序就是为了方便用户使用, 我觉得UI设计的核心就是简洁, 操作过于繁琐的程序让很大一部分用户敬而远之. 即使功能强大, 但是人们更愿意使用易于操作的软件. 近年流行起来的操作手势和逐渐趋于成 ...

  8. Nginx 之三:nginx服务器模块、web请求处理机制及事件驱动模型、进程功能和进程间通信

    一:Nginx的模块化结构设计: 1.核心模块:指的是nginx服务器运行当中必不可少的模块,这些模块提供了最基本最核心的服务,比如权限控制.进程管理.错误日志.事件驱动.正则表达式解析等,nginx ...

  9. spring事件驱动模型--观察者模式在spring中的应用

    spring中的事件驱动模型也叫作发布订阅模式,是观察者模式的一个典型的应用,关于观察者模式在之前的博文中总结过,http://www.cnblogs.com/fingerboy/p/5468994. ...

随机推荐

  1. urlEncoder

    拷贝自php的源码,url编码 //url decode //str:输入,输出 //len:str输入字符串大小 //返回值:str解码后字符串大小 int php_url_decode(char ...

  2. Linux从入门到适应(一):VSCode C++环境配置

    作为在Windows环境下习惯使用Visual Studio IDE的人,对于Linux环境下的Vim编辑使用十分难受,虽然网上很多人说vim非常牛逼和强大,但是我更加习惯于使用VS code的界面, ...

  3. POJ 1637 Sightseeing tour 建图+网络流

    题意: 给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路. 分析: 存在欧拉回路的有向图,必须满足[入度==出度],现在,有些边已经被定向,所以我们直接记录度数即 ...

  4. 合办大学 -- internal campus in China

    * 合办大学 -- internal campus in China- international campus zhejiang University- 南方科技大学 - 西交利物浦大学(Xi’an ...

  5. 一个IT工薪族的4年奋斗成果

     关于标题:为了方便传播,使用了"最简化"的一段. 过段时间,考虑改为"大学毕业4年-回顾和总结(11):一个IT工薪族的4年奋斗成果(2012年6月17日~2016年6 ...

  6. 分享大牛开发经验,浅谈java程序员职业规划

    在中国有很多人都认为IT行为是吃青春饭的,如果过了30岁就很难有机会再发展下去!其实现实并不是这样子的,在下从事.NET及JAVA方面的开发的也有8年的时间了,在这...... 在中国有很多人都认为I ...

  7. 九度oj 题目1075:斐波那契数列

    题目1075:斐波那契数列 时间限制:5 秒 内存限制:32 兆 特殊判题:否 提交:3641 解决:2100 题目描述: 编写一个求斐波那契数列的递归函数,输入n值,使用该递归函数,输出如样例输出的 ...

  8. Spark 动态(统一)内存管理模型

    作者编辑:王玮,胡玉林 一.回顾 在前面的一篇文章中我们介绍了spark静态内存管理模式以及相关知识https://blog.csdn.net/anitinaj/article/details/809 ...

  9. php.ini中date.timezone设置分析

    date.timezone设置php5默认date.timezone为utc,改为date.timezone = PRC即可解决时间相差八小时的问题,但我在php的官方文档中看了半天也没找到这个参数啊 ...

  10. redis & macOS & python

    redis & macOS & python how to install python 3 on mac os x? https://docs.python.org/3/using/ ...