To be honest, I'm not sure if I entirely understand your requirements. But if you want to make your DefaultGameEventHandler as generic as possible, I would suggest the following approach:
Instead of having a GameEventHandler interface that accepts Enums as generic EventTypes and AttributeTypes, make the GameEventHandler interface accept an EventType interface and an AttributeType interface:
public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends EventType, ATT extends AttributeType> {
public void handleEvent(final GameEvent<TYPE, ATT>... e);
public void registerListener(final GameEventListener<I> listener, final TYPE... type);
public void unregisterListener(final GameEventListener<I>... listener);
public void unregisterAllListener();
public void unregisterAllListener(final I... type);
public void processEvents();
public void processEvents(final int maxTimeInMS);
}
Here are the corresponding interfaces and the GameEvent class:
public interface EventType {
// common functionality of EventTypes, if any
}
public interface AttributeType {
// common functionality of AttributeTypes , if any
}
public class GameEvent<T extends EventType, S extends AttributeType> {
private HashMap<S, String> values;
private T type;
public void init(T type) {
this.type = type;
}
public T getType() {
return this.type;
}
public void addMessage(S t, String value) {
this.values.put(t, value);
}
public void getMessage(S t) {
this.values.get(t);
}
}
You can then create any number of Enums that implement these interfaces:
enum MyEventTypes implements EventType{TYPE_1,TYPE_2,TYPE_3}
enum MyAttributeTypes implements AttributeType{ATT_1,ATT_2,ATT_3}
If you absolutely need the interfaces to provide functionality from the Enum class, you can still specify this in the interface like so:
public interface EventType {
Enum<?> asEnum();
}
enum MyEventTypes implements EventType{
TYPE_1,TYPE_2,TYPE_3;
@Override
public Enum<?> asEnum() {return this;}
}
Now you can create a generic DefaultGameEventHandler class that implements the GameEventHandler interface:
public class DefaultGameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends EventType, ATT extends AttributeType> implements GameEventHandler<I, TYPE, ATT>{
@Override
public void handleEvent(GameEvent<TYPE, ATT>... e) {
//...
}
@Override
public void registerListener(GameEventListener<I> listener, TYPE... type) {
//...
}
@Override
public void unregisterListener(GameEventListener<I>... listener) {
//...
}
@Override
public void unregisterAllListener() {
//...
}
@Override
public void unregisterAllListener(I... type) {
//...
}
@Override
public void processEvents() {
//...
}
@Override
public void processEvents(int maxTimeInMS) {
//...
}
}
You may instantiate the DefaultGameEventHandler with enums
//MyEventTypes and MyAttributeTypes are enums implementing EventType respectively AttributeType
DefaultGameEventHandler<GameEvent<MyEventTypes, MyAttributeTypes>, MyEventTypes, MyAttributeTypes> handler = new DefaultGameEventHandler<>();
GameEvent<MyEventTypes, MyAttributeTypes> event = new GameEvent<>();
event.addMessage(MyAttributeTypes.ATT_1, "some Message");
event.init(MyEventTypes.TYPE_1);
handler.handleEvent(event);
switch (event.getType()) {
case TYPE_1:
System.out.println("TYPE_1");
break;
case TYPE_2:
System.out.println("TYPE_2");
break;
case TYPE_3:
System.out.println("TYPE_3");
break;
default:
break;
}
or also with the interfaces or any classes implementing the interfaces:
DefaultGameEventHandler<GameEvent<EventType, AttributeType>, EventType, AttributeType> handler = new DefaultGameEventHandler<>();
GameEvent<EventType, AttributeType> event = new GameEvent<>();
event.addMessage(MyAttributeTypes.ATT_1, "some Message");
event.init(MyEventTypes.TYPE_1);
handler.handleEvent(event);
EventType type = event.getType();
// To switch on the type you could use the asEnum() method
// and cast the type to the corresponding enum if possible:
if (type.asEnum().getClass() == MyEventTypes.class) {
MyEventTypes t = (MyEventTypes)type.asEnum();
switch (t) {
case TYPE_1:
System.out.println("TYPE_1");
break;
case TYPE_2:
System.out.println("TYPE_2");
break;
case TYPE_3:
System.out.println("TYPE_3");
break;
default:
break;
}
}
// Or you could also directly switch on the name of the enum (not recommended!):
switch (type.asEnum().name()) {
case "TYPE_1":
System.out.println("TYPE_1");
break;
case "TYPE_2":
System.out.println("TYPE_2");
break;
case "TYPE_3":
System.out.println("TYPE_3");
break;
default:
break;
}
EDIT - In reply to the comment from BennX:
I think, that it would be rather good just to define the Eventhandlers
and GameEvents with 2 Enums. But i think its not possible just with
enums as you already marked.
Actually I didn't want to indicate, that using Enums is no possible. You can entirely replace the interfaces in my examples with Enums, if you wish:
public class GameEvent<T extends Enum<?>, S extends Enum<?>>
public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends Enum<?>, ATT extends Enum<?>>
public class DefaultGameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends Enum<?>, ATT extends Enum<?>> implements GameEventHandler<I, TYPE, ATT>
But why force Enums on the end users of the GameEventHandler? If you do not need any common functionality in your EventType and AttributeType, then you could even go without any enums or interfaces at all and make GameEventHandler entirely generic:
public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE, ATT>
public class GameEvent<T, S>
public class DefaultGameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE, ATT> implements GameEventHandler<I, TYPE, ATT>
The example code I posted above, where one instantiates the DefaultGameEventHandler with Enums, will still work with this generic GameEventHandler. But instead of Enums, the user could also decide to use final Integers, final Strings, or any other Object for the event and attribute types.