簡體   English   中英

用Java中的通用處理程序進行事件處理

[英]Events handling with generic handlers in java

我編寫了自定義干擾/處理事件系統,通常如下所示:

事件處理程序接口:

public interface EventHandler{
}

基本事件類:

public abstract class Event<H extends EventHandler> {
    public static Class Type<H> { }
    public abstract void dispatch(H handler);
}

處理程序經理:

public class HandlerManager {
    private Map<Event.Type, List<EventHandler>> map = new HashMap<Event.Type, List<EventHandler>>();
    public void register(Event.Type<H> type, H handler) {
        if(map.get(type) == null) { map.put(type, new ArrayList<EventHandler>()); }
        map.get(type).add(handler);
    }

    public void fire(Event<H> event) {...}
    ...
}

而且一切都很好,但我想使用類似

public class DataChangeEvent<D> extends Event<DataChangeHandler<D>> {
    public static final Type<?> TYPE = new Type<?>();
    D data;
    ...
    public void dispatch(DataChangeHandler<D> handler) {
        handler.onDataChanged(this);
    }
    public D getData() { return data; }
}

public class DataChangeHandler<D> extends EventHandler {
    void onDataChanged(DataChangeEvent<D> event);
}

現在,當我向為字符串(例如,整數)生成事件的管理器注冊處理程序DataChangeHandler時,此注冊的處理程序將同時接收兩個事件,這會導致在我想讀取數據時發生ClassCastException。 我了解泛型沒有一些特殊的類,並且盡管在DataChangeHandler中定義了類型,但它們仍存儲在處理程序映射的同一列表中。

有什么辦法可以使其工作?

這似乎是一個非常非常臭的設計。 為什么要使用處理該事件類型的類來輸入事件? 那是倒退。 應使用其處理的事件類型鍵入EventHandler。

因此,我不太了解您實際要執行的操作,但我認為您基本上是在嘗試執行此操作:

private Map<Class<?>, List<EventHandler>> map;
public <T> void register(Class<? extends T> typeFilter, EventHandler<T> handler) {
    map.get(typeFilter).add(handler);
}


//...later
//safe since we used a generic method to add 
@SuppressWarnings("unchecked"); 
public void fire(Event<?> event) {
    for ( EventHandler handler : map.get(event.getClass()) ) {
        handler.onDataChanged(event);
    }
}

//or similarly:
@SuppressWarnings("unchecked"); 
public void fire(Event<?> event) {
    for ( Class<?> type : map.keySet() ) {
        if ( !type.instanceOf(event) ) continue;
        for ( EventHandler handler : map.get(type) ) {
            handler.onDataChanged(event);
        }
    }
}

這種類型的設計將過濾掉處理程序無法處理的事件。

泛型在很大程度上是編譯時功能。 如果在運行時需要類型,則需要將類作為參數傳遞並將其存儲在字段中。

恕我直言:創建干擾點的一種更優雅的方法是使用注釋。 喜歡

@EventHandler
public void onMyEvent(MyEvent event) {
   // is called when MyEvent is dispacted.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM