一個事件的基類,目標為改進j2sdk中的Observer
Posted on 2006-04-27 00:02 iceboundrock 閱讀(1066) 評論(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

??2

??3

??4

??5

??6

??7

??8

??9

?10

?11

?12

?13

?14

?15

?16

?17

?18

?19

?20

?21

?22

?23

?24

?25

?26

?27

?28

?29

?30

?31

?32

?33

?34

?35

?36

?37

?38

?39

?40

?41

?42

?43

?44

?45

?46

?47

?48

?49

?50

?51

?52

?53

?54

?55

?56

?57

?58

?59

?60

?61

?62

?63

?64

?65

?66

?67

?68

?69

?70

?71

?72

?73

?74

?75

?76

?77

?78

?79

?80

?81

?82

?83

?84

?85

?86

?87

?88

?89

?90

?91

?92

?93

?94

?95

?96

?97

?98

?99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

使用范例:
首先定義一個事件處理器的接口




接著我們就編寫一個類作為事件源(Observerable)























接著我們就編寫一個類作為事件處理器:












OK,這樣就可以了,當然我們還需要一些客戶端的代碼來將TestEventHandler的實例注冊到TestEvents的實例中監聽事件,然后我們就可以在TestEvents?類中需要的地方調用onEnter或者onExit,EventBase會自動的調用監聽器的相應方法。
對Observer/Observable的優點:1.類型安全。2.可以有多個事件函數(在接口中任意定義)而不像Observer只有一個。
缺點:1.編寫子類略現復雜。2.未做到線程安全。
歡迎評論和建議,謝謝。