Надоело каждый раз вызывать листенеры в цикле, придумал такую вещь:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ListenerProxyHolder<T> implements InvocationHandler {
    private final T proxyObject;
    private final List<T> listeners = new ArrayList<T>();
    public ListenerProxyHolder(Class<T> interfaceClass) {
        proxyObject = (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, this);
    }
    public void addListener(T t) {
        listeners.add(t);
    }
    public void removeListener(T t) {
        listeners.remove(t);
    }
    public T getProxy() {
        return proxyObject;
    }
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        for (T listener : listeners) {
            method.invoke(listener, objects);
        }
        return null;
    }
}Используется так:
public class Main {
    private ListenerProxyHolder<Listener> proxyHolder = new ListenerProxyHolder<Listener>(Listener.class);
    public Main() {
    }
    public void addListener(Listener listener) {
        proxyHolder.addListener(listener);
    }
    public void removeListener(Listener listener) {
        proxyHolder.removeListener(listener);
    }
    public void sum(int... args) {
        int sum = 0;
        for (int a : args) {
            sum += a;
            proxyHolder.getProxy().onResultReady(sum);
        }
    }
    public static void main(String[] args) {
	    Main main = new Main();
        main.addListener(new Listener() {
            @Override
            public void onResultReady(int result) {
                System.out.println("Listener 1: " + result);
            }
        });
        main.addListener(new Listener() {
            @Override
            public void onResultReady(int result) {
                System.out.println("Listener 2: " + result);
            }
        });
        main.sum(1, 2, 3);
    }
    private static interface Listener {
        void onResultReady(int result);
    }
}Таким образом код прохода по всем листенерам находится в одном месте, а не раскидан по местам вызова. Причем вместо цикла, может быть и более сложный код, вроде отправки Runnable'а в EventLoop.
Так вообще принято делать, или java-way — это писать кучу однотипного кода руками?








