Java:实施通知提供商与障碍驱动的地图
-
19-09-2019 - |
题
我已经实施了抽象通用提供商,以通知一堆通用听众 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
最好的解决方案是什么?
使用另一个非施加码备用集合 - 但是
WeakHashMap
对我来说真是太好了,因为自动为我管理弱参考使用非生成侦听器,例如简单的抽象类
equals() { return (this == object); }
实施 - 但这不是那么灵活将一些包装器用于具有简单equals()的听众 - 但此包装器不能透明
addListener(E)
呼叫者由于参考薄弱
另一个想法?
解决方案
WeakHashMap
有点破碎。它使用弱键,但不使用身份散列。除非 equals()
和 hashCode()
您的关键类型使用“身份”,您不应使用 WeakHashMap
. 。相反,您需要的东西是 WeakHashMap
和 IdentityHashMap
.
一种可能性是使用 MAPMAKER 来自Google收藏。如果密钥弱或软键,它将自动使用键的身份哈希/平等。例如:
ConcurrentMap<K, V> myMap = new MapMaker().weakKeys().makeMap();
其他提示
问题的症结似乎是您的侦听器实施是在子类别 AbstractList
, ,但不屈服 equals()
/ hashCode()
. 。我强烈建议您反对这种遗传(实施继承),因为它违反了OO-PRINCIPLE(多态性替代性原则)。
实施一个可能引用的自定义侦听器类要好得多 AbstractList
如果需要一个,那也提供了自己的 equals()
和 hashCode()
实施。