2010-08-25 175 views
2

我已經寫了自定義的dispathing /處理事件的系統,一般是這樣的:事件在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) {...} 
    ... 
} 

而且一切工作正常,但我想,當我註冊處理DataChangeHandler與經理產生事件字符串和例如用於整數使用的事件,如

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

而現在,這個註冊的處理程序將收到兩個事件是什麼原因發生ClassCastException時,我想要讀取數據。 我明白泛型沒有一些特殊的類,儘管在DataChangeHandler中定義了類型,但它們存儲在處理程序映射中的同一個列表中。

有什麼辦法可以使它工作嗎?

+0

從HandleManager中H是從哪裏來的? – 2010-08-25 18:56:09

回答

3

這似乎是一個真的很臭的設計。爲什麼應該使用處理該類型事件的類來鍵入事件?這是倒退。一個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); 
     } 
    } 
} 

這種類型的設計會過濾掉一些事件的處理程序沒辦法。

3

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

恕我直言:創建dispacter更加優雅的方式是使用註釋。 Like

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