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.

Diagramme UML version Java

Liste des différents types d'événements.

EnumEventType.java
package reactor;
 
public enum EnumEventType {
  MessageEvent, ClickEvent
}

Classe Handle qui contient l'événement et sa clé de reconnaissance.

Handle.java
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.

EventHandler.java
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.

SynchronousEventDemultplexer.java
package reactor;
 
import java.util.ArrayList;
 
public class SynchronousEventDemultplexer {
 
  public SynchronousEventDemultplexer() {
    super();
  }
 
  public EventHandler select(Handle h, ArrayList<EventHandler> 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.

Reactor.java
package reactor;
 
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
 
public class Reactor extends Thread {
  private Queue<Handle> receivedHandle;
  private SynchronousEventDemultplexer sync;
  private ArrayList<EventHandler> listEventHandler;
 
  public Reactor(SynchronousEventDemultplexer sync) {
    super();
    receivedHandle = new ConcurrentLinkedQueue<Handle>();
    listEventHandler = new ArrayList<EventHandler>();
    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.

Environment.java
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.

MessageHandler.java
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.

ClickHandler.java
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.

Main.java
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();
    }
  }
}