在软件开发过程中, 难免有信息的共享或者对象间的协作。 怎样让对象间信息共享高效, 而且耦合性低。 这是一个难题。 而耦合性高将带来编码改动牵一发而动全身的连锁效应。 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); } }
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》