• 事件驱动模型的简单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

  • 相关阅读:
    hdu 1028 Ignatius and the Princess III (n的划分)
    CodeForces
    poj 3254 Corn Fields (状压DP入门)
    HYSBZ 1040 骑士 (基环外向树DP)
    PAT 1071 Speech Patterns (25)
    PAT 1077 Kuchiguse (20)
    PAT 1043 Is It a Binary Search Tree (25)
    PAT 1053 Path of Equal Weight (30)
    c++ 常用标准库
    常见数学问题
  • 原文地址:https://www.cnblogs.com/tiancai/p/9003031.html
Copyright © 2020-2023  润新知