制作智能侦听器通知程序以避免代码重复无处不在

时间:2012-08-24 22:52:40

标签: java algorithm data-structures collections arraylist

注意:代码是线程安全的,换句话说,是单线程的。只有我可以从听众列表中删除自己。

我有1000个不同的侦听器ArrayLists,我必须通过以下代码通知:

protected void onFlushed() {
    int size = listeners.size();
    for (int i = 0; i < size; i++) {
        listeners.get(i).onFlushed();
        int newSize = listeners.size();
        if (newSize == size - 1) {
            size--;
            i--;
        } else if (newSize != size) {
            throw new ConcurrentModificationException("List was altered while iterating! oldSize=" + size + " newSize=" + newSize);
        }
    }
}

是否有一种智能方法可以创建一个Notifier类,它可以接受任何侦听器的ArrayList以及任何侦听器方法,并为我执行下面的逻辑,或者我必须为每个侦听器方法复制上面的代码?

我从Java那里问过多吗? :(

2 个答案:

答案 0 :(得分:3)

首先,我有点担心这样的事实,即大多数代码似乎都是以非常安全的方式处理并发问题。考虑对访问同一个侦听器列表的任何代码进行一些锁定。这样,您可以将此代码简化为:

protected void onFlushed() {
    synchronized(listeners) {
        for (FlushListener listener : listeners) {
            listener.onFlushed();
        }
    }
}

重复你的代码并不是太糟糕。话虽如此,如果有某些原因你需要你拥有的逻辑,你可以创建一个这样的类:

import java.util.ArrayList;
import java.util.ConcurrentModificationException;

public class Notifier<T> {
    public static interface NotificationRunnable<T> {
        public void notify(T t);
    }

    private ArrayList<T> listeners;
    public Notifier() {
        listeners = new ArrayList<T>();
    }

    public void addListener(T t) {
        listeners.add(t);
    }

    public void notifyAll(NotificationRunnable<T> nr) {
        int size = listeners.size();
        for (int i = 0; i < size; i++) {
            nr.notify(listeners.get(i));
            int newSize = listeners.size();
            if (newSize == size - 1) {
                size--;
                i--;
            } else if (newSize != size) {
                throw new ConcurrentModificationException("List was altered while iterating! oldSize=" + size + " newSize=" + newSize);
            }
        }
    }
}

然后调用它的代码看起来像:

Notifier<FlushListener> notifier = new Notifier();
notifier.addListener(new FlushListener());

public void onFlushed() {
    notifier.notifyAll(new NotificationRunnable<FlushListener>(){
        public void notify(FlushListener t) {
            t.onFlushed();
        }
    });
}

甚至可以在实际方法中将其缩小到一行:

NotificationRunnable<FlushListener> flushRunnable = new NotificationRunnable<FlushListener>(){
    public void notify(FlushListener t) {
        t.onFlushed();
    }
}

public void onFlushed() {
    notifier.notifyAll(flushRunnable);
}

答案 1 :(得分:2)

在当前的Java中,没有办法像函数式语言那样传递方法,但是你可以创建一个Function<Domain, Range>接口并传递实现该接口的对象。

您可以考虑使用Guava,它提供类似功能习语和列表理解的内容。