Posted on 2006-04-27 00:02
iceboundrock 阅读(1059)
评论(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.未做到线程安全。
欢迎评论和建议,谢谢。