
import java.util.ArrayDeque;
import java.util.Iterator;
import java.lang.reflect.Method;

class HelloWorld
{
    public static void main(String[] args) throws Exception
    {
        Delegate d = new Delegate();
        d.add(null, HelloWorld.class, "foo");
        d.add(null, HelloWorld.class, "bar");
        d.invoke();
    }
    
    public static void foo()
    {
        System.out.println("foo");
    }
    
    public static void bar()
    {
        System.out.println("bar");
    }

	static class Delegate
	{
	    ArrayDeque<Pair> methods = new ArrayDeque<Pair>();
	    Class<?>[] parameterTypes; 
	    
	    public Delegate(Class<?>... parameterTypes)
	    {
	        this.parameterTypes = parameterTypes;
	    }
	    
	    public void add(Object o, Class c, String n) throws Exception
	    {
	        Method m = c.getDeclaredMethod(n, parameterTypes);
	        methods.add(new Pair(o, m));
	    }
	    
	    public void remove(Object o, Class c, String n) throws Exception
	    {
	        Method m = c.getDeclaredMethod(n, parameterTypes);
	        methods.remove(new Pair(o, m));
	    }
	    
	    public Object invoke(Object... args) throws Exception
	    {
	        Object r = null;
	        for (Iterator<Pair> i = methods.iterator(); i.hasNext(); )
	        {
	            Pair p = i.next();
	            if (args.length == 0)
	            {
	                r = p.m.invoke(p.c);
	            }
	            else 
	            {
	                r = p.m.invoke(p.c, args);
	            }
	        }
	        return r;
	    }
	    
	    class Pair
	    {
	        public final Object c;
	        public final Method m;
	        Pair(Object c, Method m)
	        {
	            this.c = c;
	            this.m = m;
	        }
	        public int hashCode()
	        {
	            int h = 0;
	            if (c != null) h ^= c.hashCode();
	            if (m != null) h ^= m.hashCode();
	            return h;
	        }
	        public boolean equals(Object obj)
	        {
	            if (obj == null) return false; if (this == obj) return true;
	            if (!(obj instanceof Pair)) return false;
	            Pair p = (Pair)obj;
	            return (this.c == p.c) && this.m.equals(p.m);
	        }
	    }
	}
}