Ici, le pattern utilisé est un peu plus complet, notamment par l'ajout d'une clé dans chaque ''Handle'' permettant de trouver simplement l%%'%%''EventHandler'' correspondant.
{{:helloworld:design_pattern:reactor:java:reactor.png|Diagramme UML version Java}}
Liste des différents types d'événements.
package reactor;
public enum EnumEventType {
MessageEvent, ClickEvent
}
Classe ''Handle'' qui contient l'événement et sa clé de reconnaissance.
package reactor;
import java.util.EventObject;
public class Handle {
private String key;
private EventObject event;
public EventObject getEvent() {
return event;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setEvent(EventObject event) {
this.event = event;
}
}
Interface que doivent implémenter chaque traitement d'événement.
package reactor;
public interface EventHandler {
public void handleEvent();
public Handle getHandle();
public void setHandle(Handle h);
}
C'est la classe qui s'occupe de faire la correspondance entre l'événement et le traitement.
package reactor;
import java.util.ArrayList;
public class SynchronousEventDemultplexer {
public SynchronousEventDemultplexer() {
super();
}
public EventHandler select(Handle h, ArrayList list) {
if (h == null)
{
return null;
}
for (EventHandler eventHandler : list) {
if (eventHandler.getHandle().getKey().equals(h.getKey())) {
eventHandler.setHandle(h);
return eventHandler;
}
}
return null;
}
}
Le ''Reactor'' reçoit les événements, les stockent puis les traitent.
package reactor;
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Reactor extends Thread {
private Queue receivedHandle;
private SynchronousEventDemultplexer sync;
private ArrayList listEventHandler;
public Reactor(SynchronousEventDemultplexer sync) {
super();
receivedHandle = new ConcurrentLinkedQueue();
listEventHandler = new ArrayList();
this.sync = sync;
}
public void registerHandler(EventHandler e) {
listEventHandler.add(e);
}
public void removeHandler(EventHandler e) {
listEventHandler.remove(e);
}
public void startHandleEvents() {
System.out.println("Class = Reactor, Methode = startHandleEvents :: Attente événements...");
EventHandler retour = sync.select(receivedHandle.poll(), listEventHandler);
if (retour != null) {
retour.handleEvent();
}
}
public void receive(Handle h) {
System.out.println("Class = Reactor, Methode = receive :: réception d'un événement !!! " + h.getEvent().getSource());
receivedHandle.add(h);
}
public void run() {
while (true) {
startHandleEvents();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Environnement pour simuler des événements à transmettre au ''Reactor''.
package reactor;
import java.util.EventObject;
public class Environment extends Thread {
Reactor reactor;
public Environment(Reactor reactor) {
this.reactor = reactor;
}
@Override
public synchronized void run() {
int compteurClickEvent = 1;
int compteurMessageEvent = 1;
for (int i = 0; i < 5; i++) {
synchronized (reactor) {
Handle handleClick = new Handle();
handleClick.setEvent(new EventObject(EnumEventType.ClickEvent + "_" + compteurClickEvent));
handleClick.setKey(EnumEventType.ClickEvent.toString());
reactor.receive(handleClick);
compteurClickEvent++;
}
synchronized (reactor) {
Handle handleMaessage = new Handle();
handleMaessage.setEvent(new EventObject(EnumEventType.MessageEvent + "_" + compteurMessageEvent));
handleMaessage.setKey(EnumEventType.MessageEvent.toString());
reactor.receive(handleMaessage);
compteurMessageEvent++;
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Une première implémentation possible d'un traitement d'événement.
package reactor;
public class MessageHandler implements EventHandler {
private Handle handle;
@Override
public void handleEvent() {
System.out.println("Class = reactor.MessageHandler, Methode = handleEvent :: traitement evenement " + handle.getEvent().getSource());
}
@Override
public Handle getHandle() {
return handle;
}
@Override
public void setHandle(Handle h) {
handle = h;
}
}
Une deuxième implémentation possible d'un traitement d'événement.
package reactor;
public class ClickHandler implements EventHandler {
private Handle handle;
@Override
public void handleEvent() {
System.out.println("Class = reactor.ClickHandler, Methode = handleEvent :: traitement evenement " + handle.getEvent().getSource());
}
@Override
public Handle getHandle() {
return handle;
}
@Override
public void setHandle(Handle h) {
handle = h;
}
}
Le programme principal qui lie tout le monde entre eux.
package reactor;
public class Main {
public static void main(String[] args) {
try {
Reactor reactor = new Reactor(new SynchronousEventDemultplexer());
EventHandler messageHandler = new MessageHandler();
messageHandler.setHandle(new Handle());
messageHandler.getHandle().setKey(EnumEventType.MessageEvent.toString());
reactor.registerHandler(messageHandler);
EventHandler clickHandler = new ClickHandler();
clickHandler.setHandle(new Handle());
clickHandler.getHandle().setKey(EnumEventType.ClickEvent.toString());
reactor.registerHandler(clickHandler);
Thread threadReactor = new Thread(reactor);
Environment environment = new Environment(reactor);
threadReactor.start();
environment.start();
threadReactor.join();
environment.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}