Я реализовал абстрактный универсальный провайдер для группы уведомлений общих слушателей E
, потомки должны переопределить notifyListener(E)
с помощью специального кода уведомления. Для списка поддержки слушателей я выбираю WeakHashMap<K,V>
. Слушатели должны считаться слабыми ссылками:
abstract public class NotificationProvider<E> {
private Map<E, Object> listeners = new WeakHashMap<E, Object>();
public addListener(E listener) {
listeners.put(listener, null);
}
public void notifyListeners() {
for (E listener: listeners.keySet())
notifyListener(listener);
}
abstract protected void notifyListener(E listener);
}
Типичное использование:
NotificationProvider<MyListener> provider;
provider = new NotificationProvider<MyListener>() {
@Override
protected void notifyListener(MyListener listener) {
listener.myNotification();
}
}
provider.addListener(myListener1);
provider.addListener(myListener2);
provider.notifyListeners();
Все работает хорошо, но когда мне нужен AbstractList
класс-потомок в качестве слушателя, поддержка WeakHashMap
принимает только один экземпляр слушателя! Это понятно - методы hashCode()
и equals()
на слушателях возвращают одинаковое значение для всех экземпляров (пустые списки), поэтому WeakHashMap.put
заменяет только ранее добавленного слушателя.
public class MyList extends AbstractList<MyItem> {
// some implementation
}
NotificationProvider<MyList> provider;
provider = new NotificationProvider<MyList>() {
@Override
protected void notifyListener(MyList listener) {
// some implementation
}
}
MyList list1 = new MyList();
MyList list2 = new MyList();
provider.addListener(list1);
provider.addListener(list2);
provider.notifyListeners(); // only list2 instance is notified
Какое лучшее решение?
использовать другую коллекцию поддержки не hashCode - но WeakHashMap
мне так приятен, потому что автоматическое управление слабыми ссылками для меня
использовать неуниверсальный слушатель, например абстрактный класс с простой реализацией equals() { return (this == object); }
- но это не так гибко
использовать некоторую оболочку для слушателей с простым equals () - но эта оболочка не может быть прозрачной для addListener(E)
вызывающей стороны из-за слабых ссылок
Еще идеи?