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

在软件开发过程中, 难免有信息的共享或者对象间的协作。 如何让对象间信息共享高效, 并且耦合性低, 这是一个难题。 而耦合性高将带来编码修改牵一发而动全身的连锁效应, 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 [email protected] Jun 12 02:29:03 CST 2015
Received trade [email protected]
----This is devil dividing line------
Processed trade forlisiof [email protected] Jun 12 02:29:03 CST 2015
Received TradeSellEvent [email protected]
---------------------
Processed trade forwangwuof [email protected] Jun 12 02:29:03 CST 2015
Received TradeBuyEvent [email protected]

参考资料:

《Getting Started with Google Guava》

时间: 2024-10-21 01:44:04

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

让开发效率爆表的Guava ---- 基础工具篇

使用现成的库的原因, 既能减少自己开发所带来的bug, 同时又大大提高了开发效率, 当然这也是Java语言流行的一个原因----拥有海量的开源包. 本篇从Guava基础工具入手开始介绍这个广泛使用的库: package com.wenniuwuren.guava; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.HashMap; import com.google.commo

让开发效率爆表的Guava ---- Ordering排序工具

使用Guava的排序工具类, 快速实现对象的单变量排序和多变量排序, 让你的开发效率爆炸... import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import com.google.common.primitives.Ints; import java.util.Collections; import java.util.Comparator; import java.util.I

让开发效率爆表的Guava ---- Table矩阵

使用Guava对矩阵的实现, 做一些矩阵存贮等操作将大大提高效率, 而不是自己用JDK的Array去实现, 可能带来不少bug, 而且增加代码复杂度. package com.wenniuwuren.collections; import java.util.Map; import com.google.common.collect.HashBasedTable; /** * Table: 矩阵的实现 * @author wenniuwuren * */ public class TableTe

让开发效率爆表的Guava ---- Maps

本文介绍了Guava集合类Maps的使用, 比如将具有唯一主键的对象快速存入Map等... package com.wenniuwuren.guava; import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.Set; import com.google.common.base.Function; import com.google.common.collect.Li

让开发效率爆表的Guava ---- Lists列表

Guava对JDK  List的扩展, 方便增加list到list中, 方便拆分list package com.wenniuwuren.collections; import java.util.Iterator; import java.util.List; import com.google.common.collect.Lists; public class ListsTest { public static void main(String[] args) { Person perso

让开发效率爆表的Guava ---- FluentIterable迭代器

Guava提供了可以在Iterator中进行处理的功能更丰富的迭代器, 其实就像是加了一个代理, 增加一些功能. package com.wenniuwuren.collections; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.google.common.base.Function; import com.google.common.base.Joiner;

让开发效率爆表的Guava ---- Files文件操作

相信很多人最开始用JDK库对文件进行操作时, 都被繁琐重复的代码所恶心到, 当然这也是各种库出现的原因. 接下来介绍Guava的Files类, 提供了对文件操作的极大简化, 如程序员可以完全不用关心流的开关闭. 本文大致介绍了文件的复制.重命名.内容读取等对文件的基本操作. 代码示例: import com.google.common.base.Charsets; import com.google.common.collect.Lists; import com.google.common.h

让开发效率爆表的Guava ---- Concurrent并发

Guava在JDK1.5的基础上, 对并发包进行扩展, 有一些是易用性的扩展(如Monitor), 有一些是功能的完善(如ListenableFuture), 再加上一些函数式编程的特性, 使并发包的灵活性极大的提高... Monitor的使用: import com.google.common.util.concurrent.Monitor; import java.util.ArrayList; import java.util.Iterator; import java.util.List

让开发效率爆表的Guava ---- Sets

本问介绍了Guava中Sets集合类的一般使用情况, 例如集合的互斥. 交集. 并集等... package com.wenniuwuren.collections; import java.util.Iterator; import java.util.Set; import com.google.common.collect.Sets; /** * 对Sets工具类的使用 * @author wenniuwuren * */ public class SetsTest { public st