2016-06-23 25 views
0

我有一個類:使用「this.getClass()。getMethod()」檢查泛型類型是不是個好主意?

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); 
    } 
} 

中的onEvent(T事件)方法,我需要調用isApplicable(事件event)方法來檢查監聽器可以處理此事件的調用之前。

我不想增加這種方式的一些構造函數的參數:

public class GenericClass<T> { 

    private final Class<T> type; 

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

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

聽衆爲不同的事件將被存儲在相同的列表。所以我需要一些工具來檢查監聽器是否可以處理列表中的事件。

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); 
      } 
     }); 
    } 
} 

是否有一個更優雅的代碼,把這個方法:

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

以事件的接口中聲明的onEvent方法,或使抽象和定義的onEvent。這樣,就沒有必要檢查isApplicable或創建一個新的接口並在那裏聲明onEvent。所有聽衆都應該實現這個新界面 – Jaiprakash

+2

究竟是什麼*是你的問題?你已經發布的代碼將無法用於所有派生類的'Event',除非已經提供了該派生類的適當的'onEvent()'方法重載。這是意圖嗎? – EJP

+0

我在這個問題上做了一些澄清。感謝回覆。結果添加爲標記爲「最後:」的答案。 –

回答

0

正如在評論中提到,你的代碼應該,除非你的事件是Event一個實例,而不是一類的繼承它...如果Event是一個接口或抽象類,這是不可能的。

爲了保持同樣的「哲學」,我將傳遞期望的類作爲構造函數參數,並檢查事件是否是此類的實例。

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

看起來這是最正確的方式,然而代碼的第一個版本也在工作。 EventListener扮演過濾角色,因此我決定將過濾邏輯完全移到EventListener。我刪除了isApplicable(Event event)方法並添加了一個類。我不想這樣做,因爲雙EventChildClass寫「新的ListenerClass (EventChildClass.class,...)」最後我必須這樣做。 –

0

最後:

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; 
    } 

} 
相關問題