6

Having a bit of trouble with a project at the moment. I am implementing a game and I'd like to have it event-driven.

So far I have an EventHandler class which has an overloaded method depending on what type of event is generated(PlayerMove, Contact, Attack, etc)

I will have either the game driver or the class generate the events. My question is how can I efficiently handle the events without tightly coupling the event generating classes to the event handler and making the use of EDA redundant?

I want to design my own simple handler and not use the built-in Java one for this

LiamRyan
  • 1,892
  • 4
  • 32
  • 61
  • Is your application multi-threaded or you want to use the same thread for generating/handling events? – ShyJ Nov 20 '12 at 22:17
  • Well, make the same thing as what AWT does: it uses interfaces for event handlers (called listeners in AWT). – JB Nizet Nov 20 '12 at 22:18
  • Thanks guys, it's single threaded. I'm looking for a nice simplified code with explanation on how to implement what AWT does, would you have a link to something like this? – LiamRyan Nov 20 '12 at 22:22
  • It's mostly the concept that I'm having trouble with here. Should I have one static eventhandler which each event will call using its event - eg in enemy if I have an attack() method which calls EventHandler.HandleEvent(Attack). Would I have a separate class defining the Attack event - EventHandler.HandleEvent(new AttackEvent(data, target)) – LiamRyan Nov 20 '12 at 22:29
  • Here is a higher-level architecture example: https://medium.com/@wrong.about/service-boundaries-identification-example-in-e-commerce-a2c01a1b8ee9 and here is more lower-level: https://medium.com/@wrong.about/event-driven-architecture-implementation-140c51820845 – Vadim Samokhin Nov 09 '17 at 07:00

1 Answers1

9

If you want to have a single EventHandler class with overloaded methods and your event types do not have any subclasses, then this simple code, which uses reflection, should work:

public class EventHandler {
    public void handle (final PlayerMove move) {
       //... handle
    }

    public void handle (final Contact contact) {
       //... handle
    }

    public void handle (final Attack attack) {
       //... handle
    }
}

public void sendEvent (final EventHandler handler, final Object event) {
    final Method method = EventHandler.class.getDeclaredMethod ("handle", new Class[] {event.getClass ()});
    method.invoke (handler, event);
}

However, if you want to have seperate EventHandlers for different events, the following would be better.

public interface EventHandler<T extends Event> {
    void handle (T event);
}

public class PlayerMoveEventHandler implements EventHandler<PlayerMove> {
    @Override
    public void handle (final PlayerMove event) {
        //... handle
    }
}

public class EventRouter {
    private final Map<Class, EventHandler> eventHandlerMap = new HashMap<Class, EventHandler> ();

    public void sendEvent (final Event event) {
        eventHandlerMap.get (event.getClass ()).handle (event);
    }

    public void registerHandler (final Class eventClass, final EventHandler handler) {
        eventHandlerMap.put (eventClass, handler);
    }
}
ShyJ
  • 4,560
  • 1
  • 19
  • 19
  • The second example won't work. You can't pass an `Event` to a method expecting a `PlayerMove`. You would still need to use reflection to use the router to pass different types to different handlers if the handlers are expecting sub-types. Also, `Class` and `EventHandler` shouldn't be used as raw typed in `EventRouter`. – sethro Jul 02 '14 at 21:43