在运行时运行的接口代码?

时间:2018-05-22 21:29:09

标签: java events event-handling game-engine

我正在处理我正在处理的简单游戏引擎的事件处理,我的大部分内容几乎都在工作。我现在试图找出如何注册对象事件处理程序。我在想,在创建对象时,我可以创建一个运行一行代码(public void registerListener(Object listener))的接口。我知道接口不能定义构造函数,所以如果你能帮我找出另一种选择,我将不胜感激。现在,我必须在其中包含事件处理程序的所有对象的构造函数中调用前面提到的代码行,并且我认为使用接口或类似的东西将是更好的解决方案。此外,我将发布剩余的事件系统代码,以备您查看。谢谢!

EventManager类:
负责维护将响应事件的方法列表。注册EventHandler时,您将一个类作为参数传递,它将找到带有@EventHandler()注释的所有方法,并使用注释值作为事件类型。

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;

public class EventManager
{
    private HashMap<Class<? extends Event>, ArrayList<Method>> eventCallbackMap;

    public EventManager()
    {
        this.eventCallbackMap = new HashMap<>();
    }

    public void dispatchEvent(Event event)
    {
        ArrayList<Method> callbacks = eventCallbackMap.get(event.getClass());

        if(callbacks == null)
        {
            return;
        }

        for(Method callback : callbacks)
        {
            //TODO: Invoke Method
        }
    }

    public void registerListener(Object listener)
    {
        for(Method method : listener.getClass().getMethods())
        {
            if(method.isAnnotationPresent(EventHandler.class))
            {
                Class<? extends Event> value = method.getAnnotation(EventHandler.class).value();

                if(eventCallbackMap.containsKey(value))
                {
                    eventCallbackMap.get(value).add(method);
                }
                else
                {
                    ArrayList<Method> callbacks = new ArrayList<>();
                    callbacks.add(method);

                    eventCallbackMap.put(value, callbacks);
                }
            }
        }
    }
}

活动类:
非常准系统抽象类,所有自定义事件将扩展。如果你能告诉我如何改进这门课程,我将不胜感激。我很感激。

package events;

public abstract class Event
{
    public Event()
    {
    }
}

EventHandler类:
将方法定义为事件响应方法的注释。

package events;

import java.lang.annotation.*;

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler
{
    Class<? extends Event> value();
}

1 个答案:

答案 0 :(得分:1)

是。您应该使用接口,而不是注释。一个非常快速的样本可能看起来像这样。它只是一个代码草图,不确定它是否会编译。还有改进的余地,但这是基本的想法:

interface EventHandler
{
    Set<Event> eventTypes();
    void onEvent(Event event);
}

interface Event
{
    // used as a marker interface, but probably add some methods
}

enum MouseEvent implements Event
{
    ON_CLICK
    //... and whatever else
}

class OnClickEventHandler implements EventHandler
{
    public Set<Event> eventTypes()
    {
        Set<Event> events = new HashSet<>();
        events.add(MouseEvent.ON_CLICK);
        return events;
    }

    public void onEvent(Event event)
    {
        if (event == MouseEvent.ON_CLICK)
        {
            System.out.println("Mouse clicked");
        }
    }
}

class EventManager
{
    private final Map<Event, List<EventHandler>> handlers = new HashMap<>();

    public void registerListener(EventHandler handler)
    {
        for (Event eventType : handler.eventTypes())
        {
            handlers.putIfAbsent(eventType, new ArrayList<>());
            handlers.get(eventType).add(handler);
        }
    }

    public void dispatchEvent(Event event)
    {
        handlers.getOrDefault(event, Collections.emptyList())
            .forEach(handler -> handler.onEvent(event));
    }
}