tutorialspoint pattern observer dzone java collections listener observer-pattern

java - dzone - spring observer pattern



¿Buena manera de tener un oyente de colección? (5)

Bueno, si en realidad no necesita una instancia de java.util.Collection o List, puede usar un DefaultListModel . No tengo conocimiento de ninguna implementación de colección "real" con soporte de escucha / observador integrado.

¿Hay una mejor manera de tener un oyente en una colección java que envolverlo en una clase implementando el patrón de observador?


Deberías revisar Listas Esmaltadas

Contiene clases de listas observables, que activan eventos cada vez que se agregan, eliminan, reemplazan elementos, etc.


Hay muchas formas de lograrlo, a menudo uso este enfoque.

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; } } } } }


Puede usar el ForwardingSet , ForwardingList , etc., de Guava para decorar una instancia particular con el comportamiento deseado.

Aquí está mi propia implementación que solo usa APIs de JDK simples:

// 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 }; }


Eventos apache .

"Commons-Events proporciona clases adicionales para disparar y manejar eventos. Se centra en el Java Collections Framework, proporcionando decoradores a otras colecciones que activan eventos".