一个事件的基类,目标为改进j2sdk中的Observer

 

  1 //欢迎您的点评
  2
  3 import  java.lang.reflect.Method;
  4 import  java.util.ArrayList;
  5 import  java.util.Hashtable;
  6 import  java.util.Iterator;
  7
  8 import  org.apache.commons.logging.Log;
  9 import  org.apache.commons.logging.LogFactory;
 10
 11 /** */ /**
 12  * 事件基类
 13  *  @author  Richard Lee
 14  * 子类必须创建两个构造函数,一个为默认构造函数,一个为override受保护构造函数EventBase(Class handlerType)
 15   */

 16 public   abstract   class  EventBase  {
 17   ////////////////////////////////////////////
 18   // 类常量
 19  
 20   //  StringBuffer初始大小
 21   private   static   final   int  StringBufferInitSize  =   256 ;
 22  
 23   private   static   final  Log log  =  LogFactory.getLog(EventBase. class );
 24
 25   ////////////////////////////////////////////
 26   // 成员变量,在创建对象时赋值,以后不可以改变。
 27  
 28   // 同步根对象
 29   public   final  Object SyncRoot  =   new  Object();
 30  
 31   // 事件监听者列表
 32   private   final  ArrayList listeners  =   new  ArrayList();
 33  
 34   // 事件方法缓存
 35   private   final  Hashtable eventMethodCache  =   new  Hashtable();
 36  
 37   // 事件处理对象(接口)类型
 38   private   final  Class handlerType;
 39  
 40   ////////////////////////////////////////////
 41   // 私有方法
 42  
 43   /** */ /**
 44   * 检查事件处理对象的类型是否符合要求
 45   *  @param  handler
 46   *  @return
 47    */

 48   private   boolean  checkHandlerType(Object handler) {
 49    return   this .handlerType.isInstance(handler);
 50  }

 51  
 52   /** */ /**
 53   * 根据事件方法的名称查找事件函数
 54   * 约束:事件函数不能够重载(overload)
 55   *  @param  eventMethodName
 56   *  @return
 57    */

 58   private  Method getEventMethodByName(String eventMethodName) {
 59    if (eventMethodCache.containsKey(eventMethodName)) {
 60     return  (Method)eventMethodCache.get(eventMethodName);
 61   }

 62    throw   new  RuntimeException( " There is no ' "   +  eventMethodName  +   " ' event. " );
 63  }

 64  
 65   ////////////////////////////////////////////
 66   // 受保护方法
 67  
 68   /** */ /**
 69   * 受保护构造函数,创建处理接口方法缓存
 70   *  @param  handlerType
 71    */

 72   protected  EventBase(Class handlerType) {
 73    this .handlerType  =  handlerType;
 74   Method [] ms  =  handlerType.getMethods();
 75    for  ( int  i  =   0 ; i  <  ms.length; i ++ {
 76    eventMethodCache.put(ms[i].getName() , ms[i]);
 77   }

 78  }

 79  
 80   /** */ /**
 81   * 抛出事件
 82   *  @param  eventMethodName
 83   *  @param  args
 84    */

 85   protected   void  fireEvent(String eventMethodName , Object [] args) {
 86   Iterator it  =   this .listeners.iterator();
 87    while (it.hasNext()) {
 88    Object handler  =  it.next();
 89     if ( null   ==  handler)  {
 90      continue ;
 91    }

 92     try   {
 93     Method m  =  getEventMethodByName(eventMethodName);
 94     m.invoke(handler , args);
 95    }
  catch  (Throwable e)  // 捕捉所有的异常,统一通过onError方法处理。
 96     onError(eventMethodName , handler , e);
 97    }

 98   }

 99  }

100  
101   /** */ /**
102   * 事件执行过程出错的处理, 子类根据不同的异常类型进行处理
103   *  @param  eventName
104   *  @param  eventHandler
105   *  @param  e
106    */

107   protected   void  onError(String eventName , Object eventHandler, Throwable e) {
108    try {
109     if (log.isErrorEnabled()) {
110     StringBuffer msg  =   new  StringBuffer(StringBufferInitSize);
111     msg.append( " Event class: \ "" ).append(this.getClass().getName());
112     msg.append( " \ " , \ "" ).append(eventName).append( " \ "  event execute failed. Event handler: \ "" );
113      if ( null   !=  eventHandler) {
114      msg.append(eventHandler.toString());
115     }
else {
116      msg.append( " null reference " );
117     }

118     msg.append( ' " ' );
119     log.error(msg , e);
120    }

121   }
catch (Throwable ex) {
122    log.error( " onError execute failed. "  , ex);
123   }

124  }

125  
126   ////////////////////////////////////////////
127   // 公共护方法
128  
129   public   boolean  addHandler(Object handler) {
130    if (checkHandlerType(handler)) {
131     return  listeners.add(handler);
132   }

133    throw   new  IllegalArgumentException( " Handler type is invalid, addHandler method failed. " );
134  }

135  
136   public   boolean  removeHandler(Object handler) {
137    if (checkHandlerType(handler)) {
138     return  listeners.remove(handler);
139   }

140    throw   new  IllegalArgumentException( " Handler type is invalid, removeHandler method failed. " );
141  }

142  
143   public   void  removeAllHandler() {
144    this .listeners.clear();
145  }

146  
147   public   boolean  hasHandler() {
148    return   ! listeners.isEmpty();
149  }

150 }

151
152

使用范例:
首先定义一个事件处理器的接口
public   interface  ITestEventHandler  {
    
void onEnter(Object sender, Object arg);
    
void onExit(Object sender, Object arg);
}

接着我们就编写一个类作为事件源(Observerable)
/** */ /**
 * 活动的事件
 * 
@author Richard Lee
 * 非线程安全,需要使用者自行手工同步
 
*/

public   class  TestEvents  extends  EventBase  implements  ITestEventHandler  {
    
public TestEvents(){
        
this(ITestEventHandler.class);
    }


    
protected TestEvents(Class handlerType) {
        
super(handlerType);
    }


    
public void onEnter(Object sender, Object arg) {
        fireEvent(
"onEnter" , new Object[]{sender, arg});
    }


    
public void onExit(Object sender, Object arg) {
        fireEvent(
"onExit" , new Object[]{sender, arg});
    }

}

接着我们就编写一个类作为事件处理器:

public   class  TestEventHandler  implements  ITestEventHandler  {

    
public void onEnter(Object sender, Object arg) {
        System.out.println(
"OnEnter, sender: " + sender + ", arg: " + arg);
    }



    
public void onExit(Object sender, Object arg) {
        System.out.println(
"onExit, sender: " + sender + ", arg: " + arg);
    }

}


OK,这样就可以了,当然我们还需要一些客户端的代码来将TestEventHandler的实例注册到TestEvents的实例中监听事件,然后我们就可以在TestEvents 类中需要的地方调用onEnter或者onExit,EventBase会自动的调用监听器的相应方法。


对Observer/Observable的优点:1.类型安全。2.可以有多个事件函数(在接口中任意定义)而不像Observer只有一个。

缺点:1.编写子类略现复杂。2.未做到线程安全。

欢迎评论和建议,谢谢。

你可能感兴趣的:(一个事件的基类,目标为改进j2sdk中的Observer)