Posted on 2006-04-27 00:02 
iceboundrock 阅读(1076) 
评论(2)  编辑  收藏  所属分类: 
J2SE随笔 
			
			
		 
		
		 
		
				  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.未做到线程安全。
欢迎评论和建议,谢谢。