Esiste un modo migliore per avere un listener su una raccolta java piuttosto che racchiuderlo in una classe che implementa il pattern observer?Un buon modo per avere un listener della collezione?
risposta
Si dovrebbe verificare Glazed Lists
Contiene classi List osservabili, quali eventi di fuoco ogni volta che vengono aggiunti elementi, rimossi, sostituiti, ecc
Bene, se in realtà non è necessaria un'istanza java.util.Collection o List, è possibile utilizzare uno DefaultListModel. Non sono a conoscenza di eventuali implementazioni di raccolte "reali" con supporto incorporato di listener/observer.
È collegato la versione di Java 6 di DefaultListModel, che non usa Generics. La [versione di Java 7] (http://docs.oracle.com/javase/7/docs/api/javax/swing/DefaultListModel.html), che potrebbe rendere il tuo suggerimento più attraente. –
@MartinRust bene, sì, la risposta è da 2 anni prima che uscisse Java 7. Se lo aggiornerò, potrei usare Java 8 ora –
"Commons-Events fornisce classi aggiuntive per eventi di accensione e gestione. Si concentra sul framework Java Collections, fornendo decoratori ad altre raccolte che generano eventi".
Dovrebbe essere notato che questo è ancora un progetto sandbox. Uno interessante comunque. – BalusC
È possibile utilizzare il ForwardingSet, ForwardingList, ecc, da Guava a decorare un'istanza particolare con il comportamento desiderato.
Ecco la mia implementazione che utilizza solo le API JDK pianura:
// create an abstract class that implements this interface with blank implementations
// that way, annonymous subclasses can observe only the events they care about
public interface CollectionObserver<E> {
public void beforeAdd(E o);
public void afterAdd(E o);
// other events to be observed ...
}
// this method would go in a utility class
public static <E> Collection<E> observedCollection(
final Collection<E> collection, final CollectionObserver<E> observer) {
return new Collection<E>() {
public boolean add(final E o) {
observer.beforeAdd(o);
boolean result = collection.add(o);
observer.afterAdd(o);
return result;
}
// ... generate rest of delegate methods in Eclipse
};
}
ci sono molti modi per raggiungere questo - spesso io uso questo approccio
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ObservableArrayList<E> extends ArrayList<E> {
private @interface MethodId {
private static final int REMOVE = 2;
private static final int ADD = 1;
}
public interface ListObserver<E> {
void onElementAdded(E element);
void onElementRemoved(E element);
}
public ObservableArrayList(int capacity) {
super(capacity);
ensureObserver();
}
public ObservableArrayList() {
ensureObserver();
}
public ObservableArrayList(Collection<? extends E> collection) {
super(collection);
ensureObserver();
}
private List<WeakReference<ListObserver<E>>> _listObserverWeakRefList;
public void addObserver(ListObserver<E> observer) {
_listObserverWeakRefList.add(new WeakReference<ListObserver<E>> (observer));
}
private void ensureObserver() {
if (_listObserverWeakRefList == null) {
_listObserverWeakRefList = new ArrayList<>();
}
}
@Override
public boolean add(E object) {
super.add(object);
callObservable(MethodId.ADD, object);
return true;
}
@Override
public boolean remove(Object object) {
boolean removed = super.remove(object);
if (removed) callObservable(MethodId.REMOVE, object);
return removed;
}
private void callObservable(@MethodId int methodId, Object element) {
for (WeakReference<ListObserver<E>> observerRef : _listObserverWeakRefList) {
ListObserver<E> observer = observerRef.get();
if (observer != null) {
switch (methodId) {
case MethodId.ADD:
observer.onElementAdded((E) element);
break;
case MethodId.REMOVE:
observer.onElementRemoved((E) element);
break;
}
}
}
}
}
concordato. GlazedLists è eccellente. – Barend
Infatti, uno o due delle stesse persone hanno lavorato su entrambi ... –
TransformationList di Liste glazed si aspetta che dispose() venga invocato manualmente invece di utilizzare WeakReferences per gli ascoltatori ....? 0.o Deve esserci qualcosa di meglio là fuori. – user515655