ジェネリックリスナーの通知束用に抽象ジェネリックプロバイダーを実装しました。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
はリスナーインスタンスを 1 つしか受け入れません! 明らかです-メソッド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); }
が、これはそれほど柔軟ではありませんaddListener(E)
単純な equals() を使用してリスナーにラッパーを使用します -- ただし、このラッパーは弱い参照のために呼び出し元に対して透過的ではありません
別のアイデア?