繁体   English   中英

具有不同类型和数据的事件

[英]Events with different types and data

我正在用Java写一个库,该库根据类型抛出具有不同数据的不同类型的事件。

例如,这是扩展的EventObject:

public class FooEvent extends EventObject {
    private final int eventType;
    private final Object fooEventObject;

    public FooEvent(int type, Object obj){/*...*/}
    public int getEventType() {/*...*/}
    public int getEventObject() {/*...*/}
}

这是我的听众当前的样子:

FooEventListener listener = new FooEventListener() {
    @Override
    public void onDataChange(FooEvent event) {
        switch(event.getEventType()) {
            case EVENT_TYPE_BAR:
                Bars bar = (Bars)event.getEventObject();
                /*work with Bar object...*/
                break;

            case EVENT_TYPE_GOO:
                Goo goo = (Goo)event.getEventObject();
                /*work with Goo object...*/
                break;

            /* etc ...*/
        }
    }
}

我想知道这是否是解决此问题的正确方法(尽管我怀疑是这样,因为库的用户需要知道要转换为哪种类型),其中我的对象具有不同的事件类型,而我没有想要为每个事件创建一个不同的事件和侦听器。

番石榴的EventBus提供了一种略有不同的方法,可以处理多种事件类型。

不幸的是,没有一个简单的解决方案来拥有具有不同类型的类型安全事件系统。 对于每种类型,您要么必须具有1个侦听器/发布实现,要么需要向一侧介绍所有存在的事件类型。

有一种方法可以消除对instanceofswitch (type)和转换的需要: Visitor Pattern

该模式使用以下事实:事件对象知道它们自己的类型,这意味着它们可以调用正确的方法。 缺点是您需要一个包含所有类型的侦听器接口。

public class Test {

    abstract static class EventObject {
        protected abstract void deliver(EventListener listener);
    }

    static class AEvent extends EventObject {
        @Override
        protected void deliver(EventListener listener) {
            listener.onAEvent(this);
        }
    }

    static class BEvent extends EventObject {
        @Override
        protected void deliver(EventListener listener) {
            listener.onBEvent(this);
        }

    }

    interface EventListener {
        void onAEvent(AEvent event);

        void onBEvent(BEvent event);
        // ...
    }

    private static final EventListener LISTENER = new EventListener() {
        @Override
        public void onBEvent(BEvent event) {
            System.out.println("Got B Event! " + event);
        }

        @Override
        public void onAEvent(AEvent event) {
            System.out.println("Got A Event! " + event);
        }
    };

    private static void notifyListeners(EventObject event) {
        event.deliver(LISTENER);
    }

    public static void main(String[] args) {
        notifyListeners(new AEvent());
        notifyListeners(new BEvent());
    }

}

解决此问题的更好方法是使用泛型。

public class FooEvent<T> extends EventObject {
    private final T fooEventObject;

    public FooEvent(T obj){/*...*/}
    public T getEventObject() {/*...*/}
}


//usage
SomeType object = new SomeType();
new FooEvent<SomeType>(object);

我认为这是一种方法,但不是最干净的方法。 您应该创建一个抽象类

public abstract class AbstractEventType<T> extends EventObject {}

并从中扩展:

public abstract class FooEvent extends AbstractEventType<Foo> {}

public abstract class BarEvent extends AbstractEventType<Bar> {}

然后,您需要触发不同的事件,并且根据类型还需要具有不同的事件侦听器:

public interface FooEventListener {
    public void onFooChange(FooEvent fooEvent);
}

等等

如果您只想使用一种事件类型,则可以通过为每种类型创建一个处理程序方法,例如至少将代码移动到框架中以确定该类型,并避免污染“业务”代码。

public interface MyEventListener {
    public void onFooChange(EventType<Foo> eventType);
    public void onBarChange(EventType<Bar> eventType);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM