逝去的青春

          勇往直前

          2006年3月29日 #

          回調(diào)函數(shù)在Spring中的使用

          ?? 這是一種對單個方法的參數(shù)使用控制反轉(zhuǎn),把控制權(quán)和差錯處理交給框架來處理。嚴(yán)格的說,這是一種Strategy模式的特例,他們的區(qū)別就在于接口的復(fù)雜度不同。
          ?? 在Spring的JdbcTemplate中就使用了這種模式。JdbcTemplate實(shí)現(xiàn)了query()方法,參數(shù)是SQL字符串,和一個實(shí)現(xiàn)了回調(diào)接口的,將在讀取resultSet每行時被調(diào)用。

          1 public ? interface ?RowCallbackHandler?
          2 {
          3 ???? void ?processRow(ResultSet?rs)? throws ?SQLException;
          4 }
          ?


          ? query()方法封裝了對JDBC底層API的調(diào)用。

          public ? void ?query(String?sql,?RowCallbackHandler?callbackHandler)? throws ?JdbcSqlException?
          {
          ????Connection?con?
          = ? null ;
          ????PreparedStatement?ps?
          = ? null ;
          ????ResultSet?rs?
          = ? null ;
          ????
          try ?
          ????
          {
          ????????con?
          = ? < code?to?get?connection >
          ????????ps?
          = ?con.prepareStatement?(sql);
          ????????rs?
          = ?ps.executeQuery();
          ????????
          while ?(rs.next())?
          ????????
          {
          ????????????callbackHandler.processRow(rs);
          ????????}

          ????????rs.close();
          ????????ps.close();
          ????}
          ?
          ????
          catch ?(SQLException?ex)?
          ????
          {
          ????????
          throw ? new ?JdbcSqlException( " Couldn't?run?query?[ " ? + ?sql? + ? " ] " ,?ex);
          ????}

          ????
          finally ?
          ????
          {
          ????????DataSourceUtils.closeConnectionIfNecessary(
          this .dataSource,?con);
          ????}

          }


          ?? 在上面的例子中,JdbcSqlException繼承了java.lang.RuntimeException,也就是說調(diào)用者可以選擇去捕獲它,但是這不是必須的。假如實(shí)現(xiàn)了回調(diào)接口的子類里的方法出錯,而且不是RuntimeException的子類,也就是必須捕獲的異常,但是query()方法中在邏輯上是沒有辦法捕獲它的。所以Rod_Johnson把接口定義成JdbcTemplate的inner interface。這就可以JdbcTemplate就可以捕獲它。
          ?? 回調(diào)方法也是框架的一種基本方法,比如java.io.File類中的listFiles(FilenameFilter filter),FilenameFilter就是一個接口,我們實(shí)現(xiàn)這個接口中的方法accept(File dir, String name) ,這就是一個典型的回調(diào)方法。
          ?? 觀察者模式的使用符合開閉原則,并且分離了關(guān)注點(diǎn)。這種對模塊修改開發(fā),影響關(guān)閉的原則促進(jìn)了AOP面向方面編程的發(fā)展。Spring中的AOP可能就是這種思想的實(shí)現(xiàn),個人猜測而已。????
          ??? 把方法的參數(shù)放在一個類中,這樣以后要增加參數(shù)的話,不用修改方法簽名,感覺很干凈,唯一可能的缺點(diǎn)是可能對性能有所下降,不過很小。如果沒有用EJB的話,應(yīng)該差不多。

          ?? 對異常的處理,分為checked和unchecked異常,checked異常是繼承java.lang.Exception的。Unchecked異常繼承java.lang.RuntimeException。Rod_Johnson主張?jiān)趯Τ霈F(xiàn)異常后,程序不能處理,只能給予沒用的提示時用RuntimeException,因?yàn)镽untimeException容器會自動處理。關(guān)于異常的詳細(xì)說明,我也沒看明白,希望那位大蝦能指點(diǎn)指點(diǎn)。

          備注:本文主要內(nèi)容來源于Rod_Johnson的大作,強(qiáng)烈建議看原版!

          posted @ 2006-03-30 21:57 逝去的年華 閱讀(1466) | 評論 (0)編輯 收藏

          Template模式和Strategey模式

          ?????????在學(xué)習(xí)Spring的過程中經(jīng)常看到一些大蝦推薦閱讀Rod_Johnson的<Expert_One-on-One_J2EE_Design_and_Development>書,據(jù)說此書的第四章每個學(xué)java人都要看看.好不容易搞到pdf版,可惜是E文的,中文的搞不到,沒辦法只好硬著頭皮看下去。
          ???第四章主要講的是面向?qū)ο蟮脑O(shè)計(jì)模式,怎么采用一致的編碼公約,怎么利用也有的系統(tǒng).這對于理解Spring框架有很大的幫助!因?yàn)檫@是Spring之父的編程思想。):
          ???關(guān)于接口的好處及組合模式的有點(diǎn),我這里就不說了。
          ???Template模式:適用范圍,我們知道某個業(yè)務(wù)或算法的步驟,但是不知道怎么把每步的順序。Template模式采用在abstract類中有個Public and final的方法封裝了調(diào)用每步的順序,也就是說控制了工作流程。所有的繼承類也就只要實(shí)現(xiàn)每步的具體方法。這是控制反轉(zhuǎn)的一種表現(xiàn),以前都是我們在程序中去調(diào)用API中的方法,現(xiàn)在是我們實(shí)現(xiàn)API某個類中的抽象方法給該類調(diào)用!這種控制反轉(zhuǎn)的機(jī)制,是框架的代碼基礎(chǔ).比如,EJB中的Init()和destory()方法等等.Spring框架中的對數(shù)據(jù)持久層的實(shí)現(xiàn)就是很好的例子!
          下面把書中的例子COPY下:
          ? AbstractOrderEJB父類實(shí)現(xiàn)了商業(yè)邏輯,包括用戶是否金額超現(xiàn)和對大的訂單進(jìn)行打折,palceOrder()方法就是那個工作流方法。

          abstract ? class ?AbstractOrderEJB
          {
          ????
          public ? final ?Invoice?placeOrder?( int ?customerId,?InvoiceItem[]?items)
          ????????
          throws ?NoSuchCustomerException,?SpendingLimitViolation?
          ????
          {
          ????????
          int ?total? = ? 0 ;
          ????????
          for ?( int ?i? = ? 0 ;?i? < ?items.?length;?i ++ )?
          ????????
          {
          ????????????total?
          += ?getItemPrice?(items?[i])? * ?items?[i]?.getQuantity();
          ????????}

          ????????
          if ?(total? > ?getSpendingLimit?(customerId)?)
          ????????
          {
          ????????????getSessionContext()?.setRollbackOnly();
          ????????????
          throw ? new ?SpendingLimitViolation?(total,?limit);
          ????????}

          ????????
          else ? if ?(total? > ?DISCOUNT_THRESHOLD)?
          ????????
          {
          ????????????
          // ?Apply?discount?to?total
          ????????}

          ????????
          int ?invoiceId? = ?placeOrder?(customerId,?total,?items);
          ????????
          return ? new ?InvoiceImpl?(iid,?total);
          ????}


          ????
          protected ? abstract ? int ?getItemPrice(InvoiceItem?item);

          ????
          protected ? abstract ? int ?getSpendingLimit(customerId) throws ?NoSuchCustomerException;

          ????
          protected ? abstract ? int ?placeOrder( int ?customerId,? int ?total,InvoiceItem[]?items);
          ??}

          ???getItemPrice,getSpendingLimit,placeOrder這三個方法,是protected and abstract的,由子類來實(shí)現(xiàn)。
          ?? Strategey模式和Template模式比較相似.用Strategey模式對上個例子進(jìn)行改造:把三個單獨(dú)的方法放入一個接口中,工作流方法進(jìn)行如下修改:

          ?1 public ? class ?OrderEJB
          ?2 {
          ?3 ???? private ?DataHelper?dataHelper;
          ?4 ???? public ? void ?setDataHelper?(DataHelper?newDataHelper)?
          ?5 ???? {
          ?6 ???????? this .dataHelper? = ?newDataHelper;
          ?7 ????}

          ?8 ???? public ? final ?Invoice?placeOrder?( int ?customerId,?InvoiceItem[]?items)
          ?9 ???????? throws ?NoSuchCustomerException,?SpendingLimitViolation?
          10 ???? {
          11 ???????? int ?total? = ? 0 ;
          12 ???????? for ?( int ?i? = ? 0 ;?i? < ?items.length;?i ++ )?
          13 ???????? {
          14 ????????????total? += ? this .dataHelper.getItemPrice(items[i])? *
          15 ????????????items[i].getQuantity();
          16 ????????}

          17 ???????? if ?(total? > ? this .dataHelper.getSpendingLimit(customerId))?
          18 ???????? {
          19 ????????????getSessionContext()?.setRollbackOnly();
          20 ???????????? throw ? new ?SpendingLimitViolation(total,?limit);
          21 ????????}
          ?
          22 ???????? else ? if ?(total? > ?DISCOUNT_THRESHOLD)?
          23 ???????? {
          24 ???????????? // ?Apply?discount?to?total
          25 ????????}

          26 ???????? int ?invoiceId? = ? this .dataHelper.placeOrder?(customerId,?total,?items);
          27 ???????? return ? new ?InvoiceImpl?(iid,?total);
          28 ????}

          29 }

          ???Stratery模式比Temlater模式復(fù)雜點(diǎn),但是它具有更高的靈活性,對于實(shí)際項(xiàng)目一些流程的控制有很好的作用!這是本人的觀點(diǎn),不一定正確,僅供參考。
          ???
          在下面的情況下,用Stratery模式比Temlater模式更好:
          1,每步都是可變的
          2,實(shí)現(xiàn)每步的類需要一個獨(dú)立的繼承體系
          3,實(shí)現(xiàn)每步的類要和其他的類打交道
          4,實(shí)現(xiàn)每步的類要實(shí)現(xiàn)多態(tài)性

          備注:本文主要內(nèi)容來源于Rod_Johnson的大作,強(qiáng)烈建議看原版!

          posted @ 2006-03-29 20:49 逝去的年華 閱讀(1488) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 南宫市| 阳泉市| 南乐县| 旌德县| 浦县| 肥城市| 永清县| 阳山县| 巴林左旗| 西昌市| 嘉定区| 田阳县| 海淀区| 南城县| 揭西县| 西昌市| 德江县| 察隅县| 孝义市| 大石桥市| 蒙城县| 漯河市| 安吉县| 林口县| 河间市| 斗六市| 晴隆县| 博兴县| 松江区| 纳雍县| 临漳县| 利川市| 东乌珠穆沁旗| 宜章县| 扎赉特旗| 宜良县| 邯郸市| 修文县| 杭州市| 合肥市| 莲花县|