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

时间:2013-12-13 14:38:59

标签: java oop

我正在用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 ...*/
        }
    }
}

我想知道这是否是解决这个问题的正确方法(虽然我怀疑它是,因为库的用户需要知道要转换的类型),其中我有不同的事件类型与对象和我不想去做一个不同的活动&每个人的倾听者。

3 个答案:

答案 0 :(得分:3)

Guava的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());
    }

}

答案 1 :(得分:1)

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

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);

答案 2 :(得分:0)

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

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);
}

如果您只想坚持一种事件类型,那么您至少可以移动代码来确定框架的类型,并避免污染&#34;业务&#34;代码,通过为每种类型创建一个处理程序方法,例如

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