我受到AS3 中的 Signals 事件模式的启发,它取代了 flash 的原生事件。它在性能和可读性方面都做得更好。
所以我试图用Java实现它。
这种模式的主要思想是您使用对象而不是类型,从而节省了查找“Dispatcher”类来处理事件调度的时间。(调度事件是将事件发送到所有侦听器)
所以让我们进入代码:在这个示例中,我将创建 AlarmManager 并处理他的警报事件。
首先我们需要为这个事件创建我们的接口
public interface IAlarmEvent {
void alarmEventHandler(String alert);
}
现在事件本身:
public class AlarmEvent extends Signal<IAlarmEvent> implements IAlarmEvent {
public void alarmEventHandler(String alert) {
dispatch("alarmEventHandler", alert);
}
}
这是警报管理器:
public class AlarmManager {
public final AlarmEvent alarmEvent = new AlarmEvent();
public void init(){
// Dispatching the event
alarmEvent.alarmEventHandler("Wake up");
}
}
这是一个正在监听此事件的 Activity:
public class MainActivity extends Activity implements IAlarmEvent{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AlarmManager alarmManager = new AlarmManager();
alarmManager.alarmEvent.addListener(this);
alarmManager.init();
}
public void alarmEventHandler(String alert) {
Log.d("MyLog", "Event : " + alert);
}
}
这就是我编写 Signal 类的方式
public abstract class Signal<T> {
private LinkedHashMap<T, T> listeners = new LinkedHashMap<T, T>();
protected void dispatch(String methodName, Object...arguments){
Set<T> keySet = listeners.keySet();
if(keySet.size() == 0){
return;
}
Iterator<T> iterator = keySet.iterator();
Method method = null;
do{
T listener = iterator.next();
if(method == null){
try {
Class<?>[] classes = new Class<?>[arguments.length];
for(int i = 0; i < arguments.length; i++){
classes[i] = arguments[i].getClass();
}
method = listener.getClass().getMethod(methodName, classes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
try {
method.invoke(listener, arguments);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}while(iterator.hasNext());
}
public void addListener(T listener) {
listeners.put(listener, listener);
}
public void removeListener(T listener) {
listeners.remove(listener);
}
}
这种模式是:
- 快速 - 无需搜索类型并触发 eventDispatcher,它立即完成。
- 具有很好的可读性 - 只需查看类,您就可以确切地知道他发送了哪些事件,以及每个事件的外观。
但是,它运行得不好。如果我在接口中使用原语,则 Signal 无法找到方法并调用它。而且我不喜欢将方法名称传递给信号的想法。任何想法如何改善这一点?您如何看待这种模式?