【问题标题】:Java - Signals events PatternJava - 信号事件模式
【发布时间】:2012-10-16 19:29:54
【问题描述】:

我受到Signals events pattern in AS3 的启发,它取代了 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 无法找到方法并调用它。而且我不喜欢将方法名称传递给信号的想法。任何想法如何改善这一点?您如何看待这种模式?

【问题讨论】:

  • 仅供参考:Set&lt;T&gt; keySet = listeners.keySet(); if(keySet == null || keySet.size() == 0){ return; } keySet 永远不会为空
  • 我在哪里可以找到您的代码以便使用它(有一些 github repo 吗?)?我也喜欢 as3 信号。谢谢。
  • @SudoPlz 我几年前发布了这个,现在我有一个网站 gazman-sdk.com 它是新的,如果你要使用我的 sdk,我非常愿意帮助你。它刚刚开始,目前只有几个人使用。

标签: java android actionscript-3 class interface


【解决方案1】:

似乎这种模式已经在这些类中实现了

 java.util.Observable
 java.util.Observer

【讨论】:

  • 这很有趣,然而,这正是我不想做的。 Observable,只知道Observer,通过所有Observer实现的通用接口。因此,在更新方法中,我将不得不创建一个 switch case 来找出事件类型。这就是信号模式正在修复的问题。我建议您从我所依据的文章中阅读更多内容。
猜你喜欢
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 2018-10-28
  • 1970-01-01
  • 2021-04-04
相关资源
最近更新 更多