该模式实际上是监听模式的一种扩展。由事件(Event)驱动,每当有事件产生的时候,由事件分发器(EventDispatcher)分发给特定的事件处理器(Handler)处理该事件。
类图:
核心类:EventDispatcher——事件分发中心,每个来的事件都由该类分发到特定的处理者
Event——事件接口,不同的事件类型都要实现该接口
Handler——处理器接口,不同的处理器都要实现改接口
代码:
/**
* A {@link Event} is an object with a specific type that is associated
* to a specific {@link Handler}.
*/
public interface Event {
/**
* Returns the message type as a {@link Class} object. In this example the message type is
* used to handle events by their type.
* @return the message type as a {@link Class}.
*/
Class<? extends Event> getType();
}
/**
* This interface can be implemented to handle different types of messages.
* Every handler is responsible for a single of type message
* @param <E> Handler can handle events of type E
*/
public interface Handler<E extends Event> {
/**
* The onEvent method should implement and handle behavior related to the event.
* This can be as simple as calling another service to handle the event on publishing the event on
* a queue to be consumed by other sub systems.
* @param event the {@link Event} object to be handled.
*/
void onEvent(E event);
}
/**
* Handles the routing of {@link Event} messages to associated handlers.
* A {@link HashMap} is used to store the association between events and their respective handlers.
*/
public class EventDispatcher {
private Map<Class<? extends Event>, Handler<? extends Event>> handlers;
public EventDispatcher() {
handlers = new HashMap<>();
}
/**
* Links an {@link Event} to a specific {@link Handler}.
*
* @param eventType The {@link Event} to be registered
* @param handler The {@link Handler} that will be handling the {@link Event}
*/
public <E extends Event> void registerHandler(Class<E> eventType,
Handler<E> handler) {
handlers.put(eventType, handler);
}
/**
* Dispatches an {@link Event} depending on it's type.
*
* @param event The {@link Event} to be dispatched
*/
@SuppressWarnings("unchecked")
public <E extends Event> void dispatch(E event) {
Handler<E> handler = (Handler<E>) handlers.get(event.getClass());
if (handler != null) {
handler.onEvent(event);
}
}
}
/**
* The {@link AbstractEvent} class serves as a base class for defining custom events happening with your
* system. In this example we have two types of events defined.
* <ul>
* <li>{@link UserCreatedEvent} - used when a user is created</li>
* <li>{@link UserUpdatedEvent} - used when a user is updated</li>
* </ul>
* Events can be distinguished using the {@link #getType() getType} method.
*/
public abstract class AbstractEvent implements Event {
/**
* Returns the event type as a {@link Class} object
* In this example, this method is used by the {@link EventDispatcher} to
* dispatch events depending on their type.
*
* @return the AbstractEvent type as a {@link Class}.
*/
public Class<? extends Event> getType() {
return getClass();
}
}
/**
* The {@link UserCreatedEvent} should should be dispatched whenever a user has been created.
* This class can be extended to contain details about the user has been created. In this example,
* the entire {@link User} object is passed on as data with the event.
*/
public class UserCreatedEvent extends AbstractEvent {
private User user;
public UserCreatedEvent(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
/**
* The {@link UserUpdatedEvent} should should be dispatched whenever a user has been updated.
* This class can be extended to contain details about the user has been updated. In this example,
* the entire {@link User} object is passed on as data with the event.
*/
public class UserUpdatedEvent extends AbstractEvent {
private User user;
public UserUpdatedEvent(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
/**
* Handles the {@link UserCreatedEvent} message.
*/
public class UserCreatedEventHandler implements Handler<UserCreatedEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(UserCreatedEventHandler.class);
@Override
public void onEvent(UserCreatedEvent event) {
LOGGER.info("User '{}' has been Created!", event.getUser().getUsername());
}
}
/**
* Handles the {@link UserUpdatedEvent} message.
*/
public class UserUpdatedEventHandler implements Handler<UserUpdatedEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(UserUpdatedEventHandler.class);
@Override
public void onEvent(UserUpdatedEvent event) {
LOGGER.info("User '{}' has been Updated!", event.getUser().getUsername());
}
}
/**
* This {@link User} class is a basic pojo used to demonstrate user data sent along with
* the {@link UserCreatedEvent} and {@link UserUpdatedEvent} events.
*/
public class User {
private String username;
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
/**
* An event-driven architecture (EDA) is a framework that orchestrates behavior around the
* production, detection and consumption of events as well as the responses they evoke. An event is
* any identifiable occurrence that has significance for system hardware or software. <p/> The
* example below uses an {@link EventDispatcher} to link/register {@link Event} objects to their
* respective handlers once an {@link Event} is dispatched, it's respective handler is invoked and
* the {@link Event} is handled accordingly.
*
*/
public class App {
/**
* Once the {@link EventDispatcher} is initialised, handlers related to specific events have to be
* made known to the dispatcher by registering them. In this case the {@link UserCreatedEvent} is
* bound to the UserCreatedEventHandler, whilst the {@link UserUpdatedEvent} is bound to the
* {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events.
* When a user is saved, the {@link UserCreatedEvent} can be dispatched.
* On the other hand, when a user is updated, {@link UserUpdatedEvent} can be dispatched.
*
*/
public static void main(String[] args) {
EventDispatcher dispatcher = new EventDispatcher();
dispatcher.registerHandler(UserCreatedEvent.class, new UserCreatedEventHandler());
dispatcher.registerHandler(UserUpdatedEvent.class, new UserUpdatedEventHandler());
User user = new User("iluwatar");
dispatcher.dispatch(new UserCreatedEvent(user));
dispatcher.dispatch(new UserUpdatedEvent(user));
}
}