I have created a simple event manager and I want it to work properly in a multithreaded environment:
public enum EventType {
EVENT_TYPE_A,
EVENT_TYPE_B,
EVENT_TYPE_C;
}
public interface Observer {
void onEvent(EventType eventType);
}
public class ObserverManager {
private Set<Observer> m_weakReferencedObservers;
public ObserverManager() {
m_weakReferencedObservers = Collections.newSetFromMap(new WeakHashMap<Observer,Boolean>()); // allows a set of weak references
}
public void add(Observer observer){
if (observer != null) {
m_weakReferencedObservers.add(observer);
}
}
public void remove(Observer observer){
m_weakReferencedObservers.remove(observer);
}
public void callEvent(EventType eventType){
m_weakReferencedObservers.stream()
.filter(Objects::nonNull)
.forEach(observer -> observer.onEvent(eventType));
m_weakReferencedObservers.remove(null);
}
}
public class EventManager {
private Map<EventType,ObserverManager> m_observerManagers = new HashMap<>();
public void registerObserver(EventType eventType,Observer observer){
synchronized (m_observerManagers){
if (!m_observerManagers.containsKey(eventType)){
m_observerManagers.put(eventType,new ObserverManager());
}
ObserverManager observerManager = m_observerManagers.get(eventType);
observerManager.add(observer);
}
}
public void unregisterObserver(EventType eventType,Observer observer){
synchronized (m_observerManagers) {
if (!m_observerManagers.containsKey(eventType)) {
return;
}
ObserverManager observerManager = m_observerManagers.get(eventType);
observerManager.remove(observer);
}
}
public void callEvent(EventType eventType){
if (!m_observerManagers.containsKey(eventType)){
return;
}
ObserverManager observerManager = m_observerManagers.get(eventType);
observerManager.callEvent(eventType);
}
}
A few points:
- Is my use of weak references appropriate here?
- Is my use of the
synchronized
keyword appropriate here? - In general, is there a better way to implement this?
- If I want my event manager to be able to send many more different
onEvent
methods (with different prototypes), what's the best way to do it? So, instead of only havingonEvent(EventType eventType)
, I could also easily useonEvent(EventType eventType, MyClass myClass)
. I mean, in general, how can I let the user of this class create his ownonEvent()
prototype?