避免观察者代码中的多重循环
问题描述:
我有一个类AllListener
来封装多个监听器,如下所示。 问题是我必须在每个事件方法(onStart()
,onEnd()
)中编写一个循环。 这在观察者模式代码中是非常正常的方式,但它的味道很难闻。任何更好的方法来写循环一次?谢谢!避免观察者代码中的多重循环
class AllListener{
List<Listener> listeners;
void onStart(){
for(Listener l:listeners)//loop
l.onStart();
}
void onEnd(){
for(Listener l:listeners)//loop
l.onEnd();
}
}
答
使用Java的注释处理器[Little Bobby Tables学分]来生成代码。正如你所看到的那样,虽然起作用,但是与原始版本不太可读,如果你只有两种调用方法,就不值得麻烦。
避免这一点很难,因为Java仍然没有关闭。基本上,你有这些选择:
- 使用一个包装类为您的“动作”
- 到使用反射(我会考虑太这里复杂)
- 使用库(如functionaljava)
:
答
您可以编写一个包装循环的fire方法,并从onStart,onEnd方法中调用此方法,如下所示。
class AllListener {
void onStart(){
fire("onStart");
}
void onEnd(){
fire("onEnd");
}
// eventName must be same with the event handler method in Listener class.
private void fire(String eventName) {
for(Listener l : listeners) {
// Call event handler method with reflection.
l.getClass().getMethod(eventName).invoke(l);
}
}
}
答
您可以方便Java的动态代理来解决这个问题:
public class MultiListenerExample {
private ArrayList<OnClickListener> onClickListeners = new ArrayList<OnClickListener>(); private OnClickListener dispatcher;
public void performOnClick(View v) {
dispatch().onClick(v);
}
private OnClickListener dispatch() {
if (dispatcher == null) {
dispatcher = createDispatcher();
}
return dispatcher;
}
private OnClickListener createDispatcher() {
ClassLoader loader = OnClickListener.class.getClassLoader();
Class<?>[] interfaces = new Class[] { OnClickListener.class };
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for (OnClickListener listener : onClickListeners) {
// safe to call this since we implement the same interface as the object of the original invocation
method.invoke(listener, args);
}
return null;
}
};
return (OnClickListener) Proxy.newProxyInstance(loader, intefaces, handler);
}
}
由dispatch()
返回的接口上的每一个通话将被传播到被以这样的方式实现的InvocationHandler
对象,它将遍历侦听器的容器,并将对每个项目执行原始调用。
该方法可以安全地调用,因为原始调用是在与我们要调用的完全相同的接口上进行的。
只要您的侦听器没有返回值,此解决方案就可以工作。
还有第四种选择:使用Java的注释处理器生成代码。但是,除非你有几十个观察功能,否则这将是非常糟糕的做法。 – 2010-10-27 08:36:09
正确,我忘记了。我会说这种复杂性与反思方法相似。 – Landei 2010-10-27 11:39:40