?

          ??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.未做到線程安全。

          歡迎評論和建議,謝謝。

          Feedback

          # re: 一個事件的基類,目標為改進j2sdk中的Observer  回復  更多評論   

          2006-04-27 08:51 by 指教了
          1,j2sdk中的Observer/Observable難道就不類型安全?
          2,所謂“可以有多個事件函數”,沒有很大意義,一個和多個沒有本質區別;
          3,你把Observable(TestEvents)也變成一個類型Observer(ITestEventHandler),你認為這樣設計在類型層次上elegant?還有,如果真是這樣的設計,eventBase(Class handlerType)是不是有點可笑?(“自己不知道自己”?)


          “改進j2sdk中的……”這種標題還是少用為好,免得……

          # re: 一個事件的基類,目標為改進j2sdk中的Observer  回復  更多評論   

          2006-04-27 14:28 by iceboundrock
          謝謝您的指教,對于這三個方面,我是這么考慮的:
          1,j2sdk中的Observer/Observable難道就不類型安全?
          沒錯啊,因為接口設計的太粗,所以無法保證回調時一定傳入監聽器需要的類型。
          2,多個事件函數的意義在于可以清晰的表明事件的含義,并且提高效率。監聽器不必自己處理所有的事件。
          3,TestEvents實現ITestEventHandler的確不夠優雅,不過這是為了程序編寫上的方便。另外因為TestEvents可以實現很多接口,所以把事件處理類型傳遞進去,可以減少一部分工作。您覺得這塊需要如何改進呢?
          這個類的目標是改進Observer,我也的確認為對Observer做出了一些改善,所以我保留標題。

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          posts - 10, comments - 15, trackbacks - 0, articles - 0

          Copyright © iceboundrock

          主站蜘蛛池模板: 泰顺县| 都安| 鄄城县| 聂拉木县| 镇康县| 泽库县| 乃东县| 民和| 蕉岭县| 荔浦县| 富锦市| 丘北县| 靖州| 通化市| 延长县| 和硕县| 阿拉善盟| 来宾市| 米林县| 富蕴县| 安宁市| 抚远县| 玉龙| 乳源| 峨眉山市| 满城县| 崇礼县| 竹北市| 盐津县| 苍南县| 麻阳| 郧西县| 龙游县| 达尔| 百色市| 浮山县| 景洪市| 吉木乃县| 福安市| 皮山县| 嘉祥县|