事件驱动模型的简单Java实现
事件驱动模型的原理不再赘述,Swing是不错的实现。别人也有不错的博文来说明原理。
本文的目的是提供一种简单的,可供参考的简短代码,用来帮助理解该模型。
?
Project Navigator
?

?
Event
?
事件通用接口:
package org.joshua.event.events;public interface Event {}?
Click事件:
package org.joshua.event.events;public class ClickEvent implements Event {}?
Double click事件:
package org.joshua.event.events;public class DblClickEvent implements Event {}?
Listener
?
事件监听器通用接口:
package org.joshua.event.listener;import org.joshua.event.events.Event;public interface EventListener<T extends Event> {public void handleEvent(T event);}?
Click事件监听器:
package org.joshua.event.listener;import org.joshua.event.events.ClickEvent;public interface ClickEventHandler extends EventListener<ClickEvent> {}?
Double Click事件监听器:
package org.joshua.event.listener;import org.joshua.event.events.DblClickEvent;public interface DblClickEventHandler extends EventListener<DblClickEvent> {}?
Event Source
?
事件源通用接口:
package org.joshua.event.source;import org.joshua.event.events.Event;import org.joshua.event.listener.EventListener;public interface EventSource {void addEventListener(EventListener<? extends Event> listener);void removeEventListener(EventListener<? extends Event> listener);void notifyListeners(Event event);}?
模拟的按钮控件:
package org.joshua.event.source;import java.util.LinkedList;import java.util.List;import org.joshua.event.events.Event;import org.joshua.event.listener.EventListener;public class Button implements EventSource {protected List<EventListener<? extends Event>> listeners = new LinkedList<EventListener<? extends Event>>();@Overridepublic void addEventListener(EventListener<? extends Event> listener) {listeners.add(listener);}@Overridepublic void removeEventListener(EventListener<? extends Event> listener) {listeners.remove(listener);}@Overridepublic void notifyListeners(Event event) {for (EventListener listener : listeners) {try {listener.handleEvent(event);} catch (ClassCastException e) {}}}}?
Client
package org.joshua.event;import org.joshua.event.events.ClickEvent;import org.joshua.event.events.DblClickEvent;import org.joshua.event.events.Event;import org.joshua.event.listener.ClickEventHandler;import org.joshua.event.listener.DblClickEventHandler;import org.joshua.event.source.Button;import org.junit.Before;import org.junit.Test;public class Client {private Event currentEvent;private Button button;@Beforepublic void initComponent() {button = new Button();button.addEventListener(new ClickEventHandler() {@Overridepublic void handleEvent(ClickEvent event) {System.out.println("Button was clicked!");}});button.addEventListener(new DblClickEventHandler() {@Overridepublic void handleEvent(DblClickEvent event) {System.out.println("Button was double clicked!");}});}@Testpublic void testCommonEvents() {currentEvent = new ClickEvent();button.notifyListeners(currentEvent);currentEvent = new DblClickEvent();button.notifyListeners(currentEvent);}}?
?Button类中的notifyListener方法实现起来虽方便,利用了一把异常机制,但着实不推荐大家在项目中这样做。且不说性能问题,Listener的handleEvent方法里所有抛出的ClassCastException都需要重新包装。当然,我们可以使用annotation、限定类名等方式相对优雅地解决event和对应listener的mapping问题。
?
?
?
?