Posted on 2006-04-27 00:02
iceboundrock 閱讀(1061)
評論(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.未做到線程安全。
歡迎評論和建議,謝謝。