事件驱动模型的简单Java实现

事件驱动模型的原理不再赘述,Swing是不错的实现。别人也有不错的博文来说明原理。

本文的目的是提供一种简单的,可供参考的简短代码,用来帮助理解该模型。

 

Project Navigator

 

 

Event

 

事件通用接口:

Java代码  收藏代码
  1. package org.joshua.event.events;  
  2.   
  3. public interface Event {  
  4. }  

 

Click事件:

Java代码  收藏代码
  1. package org.joshua.event.events;  
  2.   
  3. public class ClickEvent implements Event {  
  4.   
  5. }  

 

Double click事件:

Java代码  收藏代码
  1. package org.joshua.event.events;  
  2.   
  3. public class DblClickEvent implements Event {  
  4.   
  5. }  

 

Listener

 

事件监听器通用接口:

Java代码  收藏代码
  1. package org.joshua.event.listener;  
  2.   
  3. import org.joshua.event.events.Event;  
  4.   
  5. public interface EventListener<T extends Event> {  
  6.       
  7.     public void handleEvent(T event);  
  8.   
  9. }  

 

Click事件监听器:

Java代码  收藏代码
  1. package org.joshua.event.listener;  
  2.   
  3. import org.joshua.event.events.ClickEvent;  
  4.   
  5.   
  6. public interface ClickEventHandler extends EventListener<ClickEvent> {  
  7.   
  8. }  

 

Double Click事件监听器:

Java代码  收藏代码
  1. package org.joshua.event.listener;  
  2.   
  3. import org.joshua.event.events.DblClickEvent;  
  4.   
  5. public interface DblClickEventHandler extends EventListener<DblClickEvent> {  
  6.   
  7. }  

 

Event Source

 

事件源通用接口:

Java代码  收藏代码
  1. package org.joshua.event.source;  
  2.   
  3. import org.joshua.event.events.Event;  
  4. import org.joshua.event.listener.EventListener;  
  5.   
  6. public interface EventSource {  
  7.   
  8.     void addEventListener(EventListener<? extends Event> listener);  
  9.       
  10.     void removeEventListener(EventListener<? extends Event> listener);  
  11.       
  12.     void notifyListeners(Event event);  
  13.   
  14. }  

 

模拟的按钮控件:

Java代码  收藏代码
  1. package org.joshua.event.source;  
  2.   
  3. import java.util.LinkedList;  
  4. import java.util.List;  
  5.   
  6. import org.joshua.event.events.Event;  
  7. import org.joshua.event.listener.EventListener;  
  8.   
  9. public class Button implements EventSource {  
  10.   
  11.     protected List<EventListener<? extends Event>> listeners = new LinkedList<EventListener<? extends Event>>();  
  12.   
  13.     @Override  
  14.     public void addEventListener(EventListener<? extends Event> listener) {  
  15.         listeners.add(listener);  
  16.     }  
  17.   
  18.     @Override  
  19.     public void removeEventListener(EventListener<? extends Event> listener) {  
  20.         listeners.remove(listener);  
  21.     }  
  22.   
  23.     @Override  
  24.     public void notifyListeners(Event event) {  
  25.         for (EventListener listener : listeners) {  
  26.             try {  
  27.                 listener.handleEvent(event);  
  28.             } catch (ClassCastException e) {  
  29.             }  
  30.         }  
  31.     }  
  32.   
  33. }  

 

Client

Java代码  收藏代码
  1. package org.joshua.event;  
  2.   
  3. import org.joshua.event.events.ClickEvent;  
  4. import org.joshua.event.events.DblClickEvent;  
  5. import org.joshua.event.events.Event;  
  6. import org.joshua.event.listener.ClickEventHandler;  
  7. import org.joshua.event.listener.DblClickEventHandler;  
  8. import org.joshua.event.source.Button;  
  9. import org.junit.Before;  
  10. import org.junit.Test;  
  11.   
  12. public class Client {  
  13.       
  14.     private Event currentEvent;  
  15.       
  16.     private Button button;  
  17.       
  18.       
  19.     @Before  
  20.     public void initComponent() {  
  21.           
  22.         button = new Button();  
  23.           
  24.         button.addEventListener(new ClickEventHandler() {  
  25.             @Override  
  26.             public void handleEvent(ClickEvent event) {  
  27.                 System.out.println("Button was clicked!");  
  28.             }  
  29.         });  
  30.           
  31.         button.addEventListener(new DblClickEventHandler() {  
  32.             @Override  
  33.             public void handleEvent(DblClickEvent event) {  
  34.                 System.out.println("Button was double clicked!");  
  35.             }  
  36.         });  
  37.           
  38.     }  
  39.       
  40.     @Test  
  41.     public void testCommonEvents() {  
  42.         currentEvent = new ClickEvent();  
  43.         button.notifyListeners(currentEvent);  
  44.           
  45.         currentEvent = new DblClickEvent();  
  46.         button.notifyListeners(currentEvent);  
  47.     }  
  48.   
  49. }  

 

 Button类中的notifyListener方法实现起来虽方便,利用了一把异常机制,但着实不推荐大家在项目中这样做。且不说性能问题,Listener的handleEvent方法里所有抛出的ClassCastException都需要重新包装。当然,我们可以使用annotation、限定类名等方式相对优雅地解决event和对应listener的mapping问题。

 

多线程事件处理机制

思路是用队列暂存事件,然后若干个事件分发器将事件分发给指定数量的事件处理线程处理。

Java代码  收藏代码
  1. package com.joshua.test.event;  
  2.   
  3. import java.util.concurrent.BlockingQueue;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6. import java.util.concurrent.LinkedBlockingQueue;  
  7.   
  8. import com.joshua.test.event.event.Event;  
  9. import com.joshua.test.event.event.EventType;  
  10. import com.joshua.test.event.handler.CreateEventHandler;  
  11.   
  12. public class EventManager {  
  13.   
  14.     private static final int EVENT_QUEUE_LENGTH = 1000;  
  15.     private static final int DISPATCHER_NUM = 2;  
  16.     private static final int EVENT_HANDLER_NUM = 10;  
  17.       
  18.     public BlockingQueue<Event> eventQueue = new LinkedBlockingQueue<Event>(EVENT_QUEUE_LENGTH);  
  19.     private ExecutorService eventHandlerPool;  
  20.       
  21.     protected EventDispatcher createDispatcher() {  
  22.         EventDispatcher dispatcher = new EventDispatcher(this.eventQueue, this.eventHandlerPool);  
  23.         dispatcher.register(EventType.CREATE, CreateEventHandler.class);  
  24.         return dispatcher;  
  25.     }  
  26.       
  27.     public void init() {  
  28.         eventHandlerPool = Executors.newFixedThreadPool(EVENT_HANDLER_NUM);  
  29.     }  
  30.       
  31.     public void start() {  
  32.         for (int i = 0; i < DISPATCHER_NUM; i++) {  
  33.             createDispatcher().start();  
  34.         }  
  35.     }  
  36.       
  37.     public void notify(Event event) {  
  38.         try {  
  39.             eventQueue.put(event);  
  40.         } catch (InterruptedException e) {  
  41.         }  
  42.     }  
  43.   
  44. }  

 

Java代码  收藏代码
  1. package com.joshua.test.event;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5. import java.util.concurrent.BlockingQueue;  
  6. import java.util.concurrent.ExecutorService;  
  7.   
  8. import com.joshua.test.event.event.Event;  
  9. import com.joshua.test.event.event.EventType;  
  10. import com.joshua.test.event.handler.EventHandler;  
  11.   
  12. @SuppressWarnings("rawtypes")  
  13. public class EventDispatcher {  
  14.   
  15.     private final BlockingQueue<Event> eventQueue;  
  16.     private final ExecutorService eventHandlerPool;  
  17.     protected final Map<EventType, Class<? extends EventHandler>> eventDispatchers = new HashMap<EventType, Class<? extends EventHandler>>();  
  18.     private Thread eventHandlingThread;  
  19.   
  20.     private volatile boolean stopped = false;  
  21.   
  22.     public EventDispatcher(BlockingQueue<Event> eventQueue, ExecutorService eventHandlerPool) {  
  23.         this.eventQueue = eventQueue;  
  24.         this.eventHandlerPool = eventHandlerPool;  
  25.         System.out.println("Event dispatcher starting...");  
  26.     }  
  27.   
  28.     Runnable createThread() {  
  29.         return new Runnable() {  
  30.             @Override  
  31.             public void run() {  
  32.                 while (!stopped && !Thread.currentThread().isInterrupted()) {  
  33.                     Event event;  
  34.                     try {  
  35.                         event = eventQueue.take();  
  36.                     } catch (InterruptedException ie) {  
  37.                         if (!stopped) {  
  38.                             System.out.println("Dispatcher thread interrupted");  
  39.                             ie.printStackTrace();  
  40.                         }  
  41.                         return;  
  42.                     }  
  43.                     if (event != null) {  
  44.                         dispatch(event);  
  45.                     }  
  46.                 }  
  47.             }  
  48.         };  
  49.     }  
  50.   
  51.     @SuppressWarnings("unchecked")  
  52.     protected void dispatch(Event event) {  
  53.         EventType type = event.getType();  
  54.         try {  
  55.             Class<? extends EventHandler> handlerClazz = eventDispatchers  
  56.                     .get(type);  
  57.             if (handlerClazz != null) {  
  58.                 EventHandler handler = handlerClazz.newInstance();  
  59.                 handler.setEvent(event);  
  60.                 eventHandlerPool.submit(handler);  
  61.             } else {  
  62.                 throw new Exception("No handler for registered for " + type);  
  63.             }  
  64.         } catch (Throwable t) {  
  65.             System.err.println("Error in dispatcher thread");  
  66.             t.printStackTrace();  
  67.             System.exit(-1);  
  68.         }  
  69.     }  
  70.   
  71.     public void register(EventType eventType,  
  72.             Class<? extends EventHandler> handler) {  
  73.         Class<? extends EventHandler> registeredHandler = eventDispatchers  
  74.                 .get(eventType);  
  75.         System.out.println("Registering " + eventType + " for "  
  76.                 + handler);  
  77.         if (registeredHandler == null) {  
  78.             eventDispatchers.put(eventType, handler);  
  79.         }  
  80.     }  
  81.   
  82.     public void start() {  
  83.         eventHandlingThread = new Thread(createThread());  
  84.         eventHandlingThread.setName("AsyncDispatcher event handler");  
  85.         eventHandlingThread.start();  
  86.         System.out.println("Event dispatcher started!");  
  87.     }  
  88.   
  89.     public void stop() {  
  90.         stopped = true;  
  91.         if (eventHandlingThread != null) {  
  92.             eventHandlingThread.interrupt();  
  93.             try {  
  94.                 eventHandlingThread.join();  
  95.             } catch (InterruptedException ie) {  
  96.                 System.out.println("Interrupted Exception while stopping");  
  97.                 ie.printStackTrace();  
  98.             }  
  99.         }  
  100.     }  
  101.   
  102. }  

  转自 http://joshuasabrina.iteye.com/blog/1812722

posted @ 2018-05-07 15:36  甜菜波波  阅读(5988)  评论(0编辑  收藏  举报