まず第一に、このコードのほとんどが、あまり安全ではない方法で並行性の問題を処理しているように見えるという事実が少し心配です。同じリスナのリストにアクセスするすべてのコードをロックすることを検討してください。そうすれば、このコードを次のように単純化できます。
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();
}
});
}
または、実際のメソッドで 1 行にまとめることもできます。
NotificationRunnable<FlushListener> flushRunnable = new NotificationRunnable<FlushListener>(){
public void notify(FlushListener t) {
t.onFlushed();
}
}
public void onFlushed() {
notifier.notifyAll(flushRunnable);
}