2016-06-23 5 views
0

Ich habe eine Klasse:Ist es eine schlechte Idee, den generischen Typ mit "this.getClass(). GetMethod()" zu überprüfen?

public class EventListener<T extends Event> { 

    private final EventHandler<T> handler; 

    public EventListener(EventHandler<T> handler) { 
     if (handler == null) { 
      throw new NullPointerException(); 
     } 
     this.handler = handler; 
    } 

    public boolean isApplicable(Event event) { 
     try { 
      this.getClass().getMethod("onEvent", event.getClass()); 
      return true; 
     } catch (NoSuchMethodException | SecurityException ex) { 
      return false; 
     } 
    } 

    public void onEvent(T event) { 
     handler.handle(event); 
    } 
} 

Vor einem Aufruf des onEvent (T Ereignis) Methode, die ich muss zu überprüfen, die isApplicable (Event-Ereignis) Methode aufrufen, dass der Hörer dieses Ereignis umgehen konnte.

Ich will nicht eine Reihe der Konstrukteurs-Parameter in einer solchen Art und Weise erhöhen:

public class GenericClass<T> { 

    private final Class<T> type; 

    public GenericClass(Class<T> type) { 
      this.type = type; 
    } 

    public Class<T> getMyType() { 
     return this.type; 
    } 
} 

Zuhörer für verschiedene Veranstaltungen werden in der gleichen Liste gespeichert werden. Also brauche ich ein Tool, um zu überprüfen, ob der Listener das Ereignis aus der Liste verarbeiten kann.

public class EventService extends Service { 

    private final ArrayList<EventListener> listeners = new ArrayList<>(); 

    public EventService(ServiceContainer serviceContainer) { 
     super(serviceContainer); 
    } 

    public ArrayList<EventListener> getListeners() { 
     return listeners; 
    } 

    public <T extends Event> void trigger(T event) { 
     listeners.stream().forEach((listener) -> { 
      if (listener.isApplicable(event)) { 
       listener.onEvent(event); 
      } 
     }); 
    } 
} 

Gibt es eine elegantere Code in dieser Methode zu setzen:

public boolean isApplicable(Event event) { 
    try { 
     this.getClass().getMethod("onEvent", event.getClass()); 
     return true; 
    } catch (NoSuchMethodException | SecurityException ex) { 
     return false; 
    } 
} 
+0

Make-Ereignis eine Schnittstelle, erklären die onEvent Methode oder es abstrakt machen und onEvent definieren. Auf diese Weise ist es nicht notwendig, nach "issApplicable" zu suchen oder eine neue Schnittstelle zu erstellen und onEvent dort zu deklarieren. Alle Zuhörer sollten diese neue Schnittstelle implementieren. – Jaiprakash

+2

Was genau ist Ihr Problem? Der von Ihnen gepostete Code schlägt für alle abgeleiteten Klassen von 'Event' fehl, es sei denn, es wurde eine geeignete 'onEvent() '- Methodenüberladung für diese abgeleitete Klasse bereitgestellt. Ist das die Absicht? – EJP

+0

Ich machte einige Klarstellungen in der Frage. Danke für die Antwort. Das Ergebnis wurde als Antwort mit "Endlich:" hinzugefügt. –

Antwort

0

Wie in den Kommentaren erwähnt, sollten Sie den Code, es sei denn Ihre Veranstaltung eine Instanz von Event und nicht einer Klasse ist es vererben ... was unmöglich ist, wenn Event eine Schnittstelle oder eine abstrakte Klasse ist.

Um die gleiche Art von "Philosophie" zu behalten, würde ich die erwartete Klasse als Konstruktorargument übergeben und prüfen, ob das Ereignis eine Instanz dieser Klasse ist.

public class EventListener<T extends Event> { 

    private final EventHandler<T> handler; 
    private final Class<T> eventClass; 

    public EventListener(EventHandler<T> handler, Class<T> eventClass) { 
     if (handler == null) { 
      throw new NullPointerException(); 
     } 
     if (eventClass == null) { 
      throw new NullPointerException(); 
     } 
     this.handler = handler; 
     this.eventClass = eventClass; 
    } 

    public boolean isApplicable(Event event) { 
     return this.eventClass.isInstance(event); 
    } 

    public void onEvent(T event) { 
     handler.handle(event); 
    } 
} 
+0

Es scheint, es ist der richtigste Weg, trotzdem funktionierte die erste Version des Codes auch. Der EventListener spielt die Filterrolle, also habe ich beschlossen, die Filterlogik vollständig auf den EventListener zu verschieben. Ich habe die Methode isApplicable (Event event) entfernt und eine weitere Klasse hinzugefügt. Ich wollte das nicht wegen einer doppelten EventChildClass schreiben "new ListenerClass (EventChildClass.class, ...)" endlich muss ich dies tun. –

0

Endlich:

public class EventService extends Service { 

    private final ArrayList<EventListener> listeners = new ArrayList<>(); 

    public EventService(ServiceContainer serviceContainer) { 
     super(serviceContainer); 
    } 

    public ArrayList<EventListener> getListeners() { 
     return listeners; 
    } 

    public <T extends Event> void trigger(T event) { 
     listeners.stream().forEach((listener) -> { 
      listener.onEvent(event); 
     }); 
    } 
} 

public class EventListener { 

    private final Consumer<Event> handler; 

    public EventListener(Consumer<Event> handler) { 
     if (handler == null) { 
      throw new NullPointerException(); 
     } 
     this.handler = handler; 
    } 

    public void onEvent(Event event) { 
     handler.accept(event); 
    } 
} 

public class SpecifiedEventListener<T extends Event> extends EventListener { 

    private final Class<T> eventClass; 

    public SpecifiedEventListener(Class<T> eventClass, Consumer<T> handler) { 
     super((Event event) -> { 
      handler.accept((T) event); 
     }); 
     if (eventClass == null 
       || handler == null) { 
      throw new NullPointerException(); 
     } 
     this.eventClass = eventClass; 
    } 

    @Override 
    public void onEvent(Event event) { 
     if (event.getClass().isAssignableFrom(eventClass)) { 
      super.onEvent(event); 
     } 
    } 

    public Class<T> getEventClass() { 
     return eventClass; 
    } 

} 
Verwandte Themen