Good way to have a Collection Listener?

前端 未结 5 1112
梦谈多话
梦谈多话 2021-02-07 04:24

Is there a better way to have a listener on a java collection than wrap it in a class implementing the observer pattern ?

相关标签:
5条回答
  • 2021-02-07 05:04

    there are many ways to achieve this - often i use this approach

    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;
                    } 
                }
            }
        }
    
    }
    
    0 讨论(0)
  • 2021-02-07 05:06

    Apache Events.

    "Commons-Events provides additional classes for firing and handling events. It focusses on the Java Collections Framework, providing decorators to other collections that fire events."

    0 讨论(0)
  • 2021-02-07 05:17

    You should check out Glazed Lists

    It contains observable List classes, which fire events whenever elements are added, removed, replaced, etc

    0 讨论(0)
  • 2021-02-07 05:17

    You can using the ForwardingSet, ForwardingList, etc., from Guava to decorate a particular instance with the desired behavior.

    Here's my own implementation that just uses plain JDK APIs:

    // 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
    
        };
        }
    
    0 讨论(0)
  • 2021-02-07 05:21

    Well, if you don't actually need a java.util.Collection or List instance, you could use a DefaultListModel. I'm not aware of any "real" Collection implementations with builtin listener/observer support.

    0 讨论(0)
提交回复
热议问题