snowolf

          這樣的一種生活
          posts - 23, comments - 5, trackbacks - 0, articles - 11

          使用Annotations設(shè)計(jì)一個(gè)MVC框架

          Posted on 2006-02-10 15:56 snowolf 閱讀(289) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JAVA類(lèi)
          Annotations能夠幫助你去掉應(yīng)用組件之間的耦合

          摘要

          Model-View-Controller (MVC)是一種軟件架構(gòu),它可以將應(yīng)用程序的數(shù)據(jù)模型,用戶接口,以及控制邏輯分開(kāi), 使其成為獨(dú)立的組件.這樣一來(lái),對(duì)其中一個(gè)組件的修改而產(chǎn)生的對(duì)其他組件的影響能夠被降到最低. 在這篇文章中,你將學(xué)習(xí)到如何使用annotation來(lái)設(shè)計(jì)一個(gè)幾乎能夠完全去掉model和view之間耦合的繼承的MVC的框架.

          版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必保留以下作者信息和鏈接
          作者:Riccardo Govoni;wenzi_33
          原文:http://www.matrix.org.cn/resource/article/44/44204_Annotations+MVC.html
          關(guān)鍵字:annotations;MVC;Framework

          當(dāng)設(shè)計(jì)一個(gè)應(yīng)用程序時(shí), 清晰的分離該程序的不同邏輯組件, 總是被證明是有益的. 同時(shí)也存在許多不同的模式來(lái)幫助開(kāi)發(fā)者實(shí)現(xiàn)這個(gè)目標(biāo)。其中最有名同時(shí)也最常用的自然是Model-View-Controller (MVC)了, 它能夠?qū)⒚總€(gè)應(yīng)用程序(或者應(yīng)用程序的一部分)分成三個(gè)不同功能的組件,并且定義了把他們聯(lián)結(jié)在一起的規(guī)則。Swing本身就是基于這個(gè)模式的,而且每個(gè)使用Struts,這個(gè)流行的開(kāi)發(fā)Web應(yīng)用框架的人也都了解隱藏在MVC后面的理論.

          這篇文章介紹了怎么樣通過(guò)使用annotation而增加一個(gè)新的組件來(lái)加強(qiáng)MVC,使其能夠更加方便地去掉models跟views之間的耦合。這篇文章介紹了一個(gè)叫Stamps的開(kāi)源庫(kù), 它是基于MVC組件之上的,但它去除了所有在開(kāi)發(fā)MVC時(shí)所需的, 在models, views和controllers之間建立聯(lián)系的負(fù)擔(dān)。

          基礎(chǔ)知識(shí): MVC和annotations

          正如MVC這個(gè)名字所指出的, Model-View-Controller模式建議將一個(gè)應(yīng)用程序分成以下三個(gè)組件:
          ·Model: 包含了數(shù)據(jù)模型和所有用來(lái)確定應(yīng)用程序狀態(tài)的信息。 它一般來(lái)說(shuō)是有條理的并且獨(dú)立于其他組件的。
          ·View: 從不同于model的角度出發(fā),它定義了存儲(chǔ)在模型中數(shù)據(jù)的展現(xiàn)方式。它通常被認(rèn)為是你的應(yīng)用程序的用戶界面(或者GUI),或者以Web應(yīng)用為例,場(chǎng)景就是你通過(guò)瀏覽器看到的頁(yè)面。
          ·Controller: 它代表應(yīng)用程序的邏輯部分。在這里,它定義了一個(gè)用戶如何和應(yīng)用程序進(jìn)行交互并且也定義了用戶行為是如何映射到model的改變。

          這些組件緊密的聯(lián)系在一起: 用戶影響view, 反過(guò)來(lái)view通知controller來(lái)更新model.最終model又更新view來(lái)反映它的新?tīng)顟B(tài)。圖1就展現(xiàn)了這種典型的MVC結(jié)構(gòu)。

          2006_02_08_232846_XtnRHlDmNe.jpg
          圖1. 一個(gè)典型的MVC結(jié)構(gòu)

          作為J2SE 5.0所提供的一個(gè)新的功能,annotations允許開(kāi)發(fā)者往classes,methods,fields,和其他程序元素中增加元數(shù)據(jù)。就像反射機(jī)制一樣,之后很多應(yīng)用程序?yàn)榱四承┰蚰茉谶\(yùn)行時(shí)期獲取并使用那些元數(shù)據(jù)。因?yàn)镴2SE 5.0只是定義了怎么樣編寫(xiě)和讀取annotations,并沒(méi)有說(shuō)明在哪里使用他們(象@Override這樣的用于提前定義的例外),開(kāi)發(fā)者擁有無(wú)窮多的在許多不同場(chǎng)合使用他們的可能性:文檔編寫(xiě),與對(duì)象相關(guān)的映射,代碼生成,等等.. Annotations已經(jīng)變的十分流行,以至于大多數(shù)框架和庫(kù)都更新自己來(lái)支持他們。至于更多的關(guān)于MVC和annotations的信息請(qǐng)參見(jiàn)資源。

          超越MVC: dispatcher

          就像前文提到的一樣,models和views之間的一些耦合是必要的因?yàn)楹笳弑仨毞从城罢叩臓顟B(tài)。普通Java程序使用直接或間接的耦合將組件綁定在一起。直接耦合發(fā)生在當(dāng)view和model之間有一個(gè)直接相關(guān)的時(shí)候,model包含一列需要維持的views。間接耦合通常發(fā)生在一個(gè)基于事件分派的機(jī)制中。Model會(huì)在它狀態(tài)改變時(shí)激發(fā)事件,同時(shí)一些獨(dú)立的views會(huì)將他們自己注冊(cè)成事件偵聽(tīng)器。

          通常我們比較青睞間接耦合因?yàn)樗筸odel完全不知道view的存在,相反view必須和model保持一定的聯(lián)系從而將自己注冊(cè)到model上。在這篇文章里我將介紹的框架就是使用間接耦合,但是為了更好的降低組件之間的耦合,view必須不知道m(xù)odel的存在;也就是說(shuō),model和view沒(méi)有被綁定在一起。

          為了實(shí)現(xiàn)這個(gè)目標(biāo),我已經(jīng)定義了一個(gè)新的組件,就是dispatcher,它能作為一個(gè)存在于views和models之間的分離層。它能處理models和views雙方之間的注冊(cè)并且分派由model激發(fā)的事件到注冊(cè)的views上。它使用java.beans.PropertyChangeEvent對(duì)象來(lái)表現(xiàn)由model傳送到view的事件;然而,這個(gè)框架的設(shè)計(jì)是足夠開(kāi)放的,它可以支持不同事件類(lèi)型的實(shí)現(xiàn)。

          管理注冊(cè)的views列表的負(fù)擔(dān)于是就從model上移開(kāi)了,同時(shí),因?yàn)関iew只和這個(gè)獨(dú)立于應(yīng)用程序的dispatcher有關(guān),view不知道m(xù)odel的存在。如果你熟悉Struts內(nèi)部,你也許能夠看出Struts的controller就是在履行這樣一個(gè)任務(wù),它將Actions和他們關(guān)聯(lián)的JSP(JavaServer Pages)表現(xiàn)頁(yè)面聯(lián)系在一起。

          現(xiàn)在,我們所設(shè)計(jì)的MVC框架就像圖2所描述的一樣。Dispatcher在其中擔(dān)當(dāng)了一個(gè)于controller相稱(chēng)的角色。

          2006_02_08_233016_NNAtmqYNNs.jpg
          圖2.擁有額外dispatcher組件的改進(jìn)的MVC框架

          由于dispatcher必須是獨(dú)立于應(yīng)用程序的,所以必須定義一些通用的聯(lián)結(jié)models和views的規(guī)范。我們將使用annotations來(lái)實(shí)現(xiàn)這種聯(lián)結(jié),它將會(huì)被用來(lái)標(biāo)注views并且確定哪個(gè)view是受哪個(gè)model的影響的,及這種影響是怎么樣的。通過(guò)這種方式,annotations就像是貼在明信片上的郵票一樣,驅(qū)動(dòng)dispatcher來(lái)執(zhí)行傳遞model事件的任務(wù)(這就是這一框架名字的由來(lái))。


          應(yīng)用實(shí)例

          我們將使用一個(gè)簡(jiǎn)單的計(jì)秒器應(yīng)用程序做該框架的一個(gè)應(yīng)用實(shí)例:它允許用戶設(shè)置時(shí)間周期來(lái)記數(shù)和啟動(dòng)/停止這個(gè)定時(shí)器。 一旦過(guò)去規(guī)定的時(shí)間,用戶將會(huì)被詢問(wèn)是否取消或者重啟這個(gè)定時(shí)器。這個(gè)應(yīng)用程序的完全源代碼可以從項(xiàng)目主頁(yè)上找到。

          2006_02_08_233211_otZImPhZpB.jpg
          圖3.一個(gè)簡(jiǎn)單的應(yīng)用程序

          這個(gè)modle是非常簡(jiǎn)單的,它只存儲(chǔ)兩個(gè)屬性:周期和已經(jīng)過(guò)去的秒數(shù)。注意當(dāng)它其中一個(gè)屬性發(fā)生變化時(shí)它是如何使用java.beans.PropertyChangeSuppor來(lái)激發(fā)事件。
          public class TimeModel {

             public static final int DEFAULT_PERIOD = 60;

             private Timer timer;
             private boolean running;

             private int period;
             private int seconds;

             private PropertyChangeSupport propSupport;

             /**
              * Getters and setters for model properties.
              */

             /**
              * Returns the number of counted seconds.
              *
              * @return the number of counted seconds.
              */
             public int getSeconds() {
                return seconds;
             }

             /**
              * Sets the number of counted seconds. propSupport is an instance of PropertyChangeSupport
              * used to dispatch model state change events.
              *
              * @param seconds the number of counted seconds.
              */
             public void setSeconds(int seconds) {
                propSupport.firePropertyChange("seconds",this.seconds,seconds);
                this.seconds = seconds;
             }

             /**
              * Sets the period that the timer will count. propSupport is an instance of PropertyChangeSupport
              * used to dispatch model state change events.
              *
              * @param period the period that the timer will count.
              */
             public void setPeriod(Integer period){
                propSupport.firePropertyChange("period",this.period,period);
                this.period = period;
             }

             /**
              * Returns the period that the timer will count.
              *
              * @return the period that the timer will count.
              */
             public int getPeriod() {
                return period;
             }

             /**
              * Decides if the timer must restart, depending on the user answer. This method
              * is invoked by the controller once the view has been notified that the timer has
              * counted all the seconds defined in the period.
              *
              * @param answer the user answer.
              */
             public void questionAnswer(boolean answer){
                if (answer) {
                   timer = new Timer();
                   timer.schedule(new SecondsTask(this),1000,1000);
                   running = true;
                }
             }

             /**
              * Starts/stop the timer. This method is invoked by the controller on user input.
              */
             public void setTimer(){
                if (running) {
                   timer.cancel();
                   timer.purge();
                }
                else {
                   setSeconds(0);
                   timer = new Timer();
                   timer.schedule(new SecondsTask(this),1000,1000);
                }

                running = !running;
             }

             /**
              * The task that counts the seconds.
              */
             private class SecondsTask extends TimerTask {

                /**
                 * We're not interested in the implementation so I omit it.
                 */

             }
          }


          Controller只定義了用戶可以執(zhí)行的并且能夠從下列接口抽象出來(lái)的actions。
          public interface TimeController {

             /**
              * Action invoked when the user wants to start/stop the timer
              */
             void userStartStopTimer();

             /**
              * Action invoked when the user wants to restart the timer
              */
             void userRestartTimer();

             /**
              * Action invoked when the user wants to modify the timer period
              *
              * @param newPeriod the new period
              */
             void userModifyPeriod(Integer newPeriod);
          }


          你可以使用你自己喜歡的GUI編輯器來(lái)畫(huà)這個(gè)view。出于我們自身的情況,我們只需要幾個(gè)公共的methods就可以提供足夠的功能來(lái)更新view的fields,如下面的這個(gè)例子所示:
          /**
              * Updates the GUI seconds fields
              */
             public void setScnFld(Integer sec){
                // scnFld is a Swing text field
                SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                      scnFld.setText(sec.toString());
                   }
                });
             }


          在這里我們注意到我們正在使用POJOs (plain-old Java objects),同時(shí)我們不用遵守任何編碼習(xí)慣或者實(shí)現(xiàn)特定的接口(事件激發(fā)代碼除外)。剩下的就只有定義組件之間的綁定了。

          事件分派annotations

          綁定機(jī)制的核心就是@ModelDependent annotation的定義:
          @Retention(RetentionPolicy.RUNTIME) 
          @Target(ElementType.METHOD)
          public @interface ModelDependent {

             String modelKey() default "";

             String propertyKey() default "";

             boolean runtimeModel() default false;

             boolean runtimeProperty() default false;

          }


          這個(gè)annotation能被用在view的methods上,同時(shí)dispatcher也會(huì)使用這些提供的參數(shù)(即modelKey和propertyKey)來(lái)確定這個(gè)view將會(huì)響應(yīng)的model事件。這個(gè)view既使用modelKey參數(shù)來(lái)指定它感興趣的可利用的models又使用propertyKey參數(shù)來(lái)匹配分配的java.beans.PropertyChangeEvents的屬性名稱(chēng)。

          View method setScnFld()因此被標(biāo)注以下信息(這里,timeModel提供了用來(lái)將model注冊(cè)到dispatcher上的key):
          /**
              * Updates the GUI seconds fields
              */
             @ModelDependent(modelKey = "timeModel", propertyKey = "seconds")
             public void setScnFld(final Integer sec){
                // scnFld is a Swing text field
                SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                      scnFld.setText(sec.toString());
                   }
                });
             }


          由于dispatcher既知道m(xù)odel激發(fā)的事件又知道事件本身-例如,它知道關(guān)聯(lián)的modelKey和propertyKey-這是唯一需要用來(lái)綁定views和models的信息。Model和view甚至不需要分享通信接口或者共用的數(shù)據(jù)庫(kù)。

          借助我們討論的綁定機(jī)制,我們可以輕易的改變潛在的view而不改變其他任何東西。下面的代碼是按照使用SWT(Standard Widget Toolkit)而不是Swing實(shí)現(xiàn)的同一個(gè)method:
          @ModelDependent(modelKey = "timeModel", propertyKey = "seconds")
             public void setScnFld(final Integer sec){
                Display.getDefault().asyncExec(new Runnable() {
                   public void run() {
                      secondsField.setText(sec.toString());
                   }
                });
             }


          一個(gè)完全沒(méi)有耦合的系統(tǒng)存在以下優(yōu)點(diǎn):View可以更加容易地適應(yīng)model地改變,盡管model通常都是穩(wěn)定地,相反view是經(jīng)常被改變。加上系統(tǒng)可以通過(guò)使用GUI編輯器或者其他源碼生成器來(lái)設(shè)計(jì),避免了將生成地代碼與model-view通信代碼混合在一起。又由于model-view的綁定信息是和源碼關(guān)聯(lián)的元數(shù)據(jù),于是也相對(duì)容易把它應(yīng)用到IDE生成的GUIs或者將已經(jīng)存在的應(yīng)用程序轉(zhuǎn)化成這個(gè)框架。加之擁有單獨(dú)的基礎(chǔ)代碼,view和model可以被當(dāng)作是獨(dú)立組件來(lái)開(kāi)發(fā),這很可能簡(jiǎn)化了應(yīng)用程序的開(kāi)發(fā)過(guò)程。組件測(cè)試也可以被簡(jiǎn)化,因?yàn)槊總€(gè)組件可以被單獨(dú)地測(cè)試,并且出于調(diào)試的目的,我們可以用假的model和view來(lái)代替真實(shí)的組件。

          然而,這里也存在許多缺點(diǎn)。因?yàn)楝F(xiàn)在當(dāng)使用接口和公共的classes來(lái)綁定model和view時(shí),我們不能再提供編譯時(shí)期的安全性了,可能出現(xiàn)的打字錯(cuò)誤將導(dǎo)致組件之間一個(gè)綁定的遺漏,從而導(dǎo)致出現(xiàn)運(yùn)行時(shí)期的錯(cuò)誤。

          通過(guò)使用@ModelDependent的討論過(guò)的modelKey和propertyKey元素,你可以定義model和view之間靜態(tài)的聯(lián)系。然而,現(xiàn)實(shí)世界的應(yīng)用程序證明view必須能夠經(jīng)常動(dòng)態(tài)的適應(yīng)變化的models和應(yīng)用程序的狀態(tài):考慮到用戶界面的不同部分能夠在應(yīng)用程序的生命周期內(nèi)被創(chuàng)造和刪除。因此我將介紹怎么使用這個(gè)框架與其他常用技術(shù)一起來(lái)處理此類(lèi)情形。

          動(dòng)態(tài)MVC綁定

          對(duì)于那些依賴XML綁定(或者其他一些基于配置文件的聲明性綁定)的框架,存在一個(gè)問(wèn)題那就是靜態(tài)綁定規(guī)則。在這些框架下,動(dòng)態(tài)變化是不可能的,于是通常開(kāi)發(fā)者決定每次將冗余的綁定信息與一些使用正確綁定的判定算法耦合在一起。

          為了巧妙的解決這個(gè)問(wèn)題,Stamps框架提供了兩種方式在運(yùn)行時(shí)期改變綁定。 第一種方式是,views和models可以采用事件監(jiān)聽(tīng)器與GUI窗口小部件聯(lián)合的方式在dispatcher上注冊(cè)和注銷(xiāo)。這樣允許特定的views只在需要他們的時(shí)候被通知到。例如,一個(gè)與應(yīng)用程序有聯(lián)系的監(jiān)視控制臺(tái)可以只在用戶請(qǐng)求的時(shí)候與被它監(jiān)視的對(duì)象綁定在一起。

          第二種方式是利用@ModelDependent annotation提供的兩個(gè)元素runtimeModel() 和 runtimeProperty()。他們指明了某個(gè)確定的model和它的分配事件會(huì)在運(yùn)行時(shí)期被確定。如果這兩個(gè)設(shè)定中有一個(gè)是正確的,那么各自的key(modelKey 或propertyKey)會(huì)在view上被method調(diào)用來(lái)得到需要使用的值。例如:一個(gè)負(fù)責(zé)顯示一組新channels (每個(gè)channel就是一個(gè)model)的view,它就依賴于用戶的輸入來(lái)確定需要綁定的channel。

          這種情形的實(shí)例如下:
          // This method is invoked to display all the messages of one news channel
             @ModelDependent(modelKey = "dynamicChannel", propertyKey = "allmessages" , runtimeModel = true)
             public void setAllMessages(java.util.List messages) {
                // Updates the user interface
             }

             public String getDynamicChannel() {
                // Returns the channel requested by the user
             }


          附加的annotations

          由于世界并不完美,一些附加的annotations被定義來(lái)幫助解決現(xiàn)實(shí)世界的案例。@Namespace允許開(kāi)發(fā)者為了更好的管理model domain將其再細(xì)分成不同的部分。由于單獨(dú)一個(gè)dispatcher可以處理多個(gè)models,model keys中將出現(xiàn)的沖突。因此,它能將成群的models和相關(guān)的views分到不同的但同屬一個(gè)namespace下的domains中去, 這樣一來(lái),他們就不會(huì)干擾對(duì)方。

          @Transform annotation提供了on-the-fly對(duì)象轉(zhuǎn)化, 從包含在model事件中的對(duì)象到被receiving views接受的對(duì)象的。因而,這個(gè)框架就可以適應(yīng)已存的代碼而不需要做任何的改動(dòng)。這個(gè)annotation接受一個(gè)注冊(cè)在有效轉(zhuǎn)化上的單一參數(shù)(被定義成一個(gè)特殊接口的實(shí)現(xiàn))。

          @Refreshable annotation能通過(guò)標(biāo)注model的屬性來(lái)支持前面討論的動(dòng)態(tài)連接和分離views。使用這個(gè)annotation,該框架可以處理靜態(tài)和動(dòng)態(tài)的MVC布局,在不同的時(shí)間把不同的views綁定到model上。

          要理解@Refreshable的使用,我們必須回到之前的那個(gè)監(jiān)控控制臺(tái)的例子。這個(gè)控制臺(tái)(用MVC的術(shù)語(yǔ)來(lái)說(shuō)就是一個(gè)view)可以動(dòng)態(tài)地綁定和離開(kāi)model,取決于用戶的需要。當(dāng)控制器連接到model的時(shí)候@Refreshable annotation可以被用來(lái)讓這個(gè)控制器隨時(shí)了解其model的狀態(tài)。當(dāng)一個(gè)view連接到這個(gè)框架時(shí),它必須在當(dāng)前model的狀態(tài)下被更新。因此,dispatcher掃描model尋找@Refreshable annotations并且生成與view它本身從model普通接受到的相同的事件。這些事件接著被之前討論過(guò)的綁定機(jī)制分派。

          分布式MVC網(wǎng)絡(luò)

          Dispatcher有一個(gè)很重的負(fù)擔(dān)那就是它負(fù)責(zé)處理事件的傳送周期中所有重型信息的傳遞:
          ·        Model激發(fā)一個(gè)事件用來(lái)確定它已經(jīng)經(jīng)歷過(guò)的一些改變, dispatcher處理通知model.
          ·        Dispatcher掃描所有注冊(cè)在它那里的views, 尋找@ModelDependent annotations, 這些annotations明確了views希望通知的改變及當(dāng)每個(gè)model事件發(fā)生時(shí),需要在views上調(diào)用的method.
          ·        如果需要,轉(zhuǎn)化將會(huì)被用于事件數(shù)據(jù)上.
          ·        view method在被調(diào)用時(shí)會(huì)從被激發(fā)的事件里抽取參數(shù),接著view會(huì)更新自己.

          從另一個(gè)方面來(lái)講,當(dāng)一個(gè)新view在dispatcher上注冊(cè)時(shí):
          ·        View告訴dispatcher有關(guān)modelKey的信息,modelkey能確定它將被連接到哪一個(gè)model上(該model的事件將負(fù)責(zé)組裝view)
          ·        如果需要,dispatcher掃描model尋找@Refreshable annotations并使用他們來(lái)生產(chǎn)將要及時(shí)更新view假的model事件
          ·        這些事件將通過(guò)使用上述的順序被分派, 接著view被更新.

          所有這些既不涉及view也不涉及model的工作,他們站在他們各自的信息通信渠道的兩端.無(wú)所謂這些信息是在一個(gè)本地JVM內(nèi)部傳輸還是在多個(gè)遠(yuǎn)程主機(jī)上的JVM之間傳輸.如果想將本地應(yīng)用程序轉(zhuǎn)化成Client/Server應(yīng)用程序所需的只是簡(jiǎn)單地改變dispatcher里面的邏輯,而model和view都不會(huì)受影響.下圖就是一個(gè)示例: 

          2006_02_08_233827_rlIDvGWfPI.jpg 
          圖4. 一個(gè)基于分布式網(wǎng)路建立的MVC.

          如上圖所示,單一的dispatcher被一個(gè)與model處在同一個(gè)host上的transmitter(it.battlehorse.stamps.impl.BroadcastDispatcher的一個(gè)instance)和一個(gè)(或多個(gè)) 與view處在同一個(gè)host上的receiver(it.battlehorse.stamps.impl.FunnelDispatcher)所取代. Stamps 框架默認(rèn)的實(shí)現(xiàn)使用了一個(gè)創(chuàng)建于JGroups上的消息傳送層, JGroups是一個(gè)可靠的多點(diǎn)傳送通信的工具包,象網(wǎng)絡(luò)傳輸機(jī)制(但是不同的實(shí)現(xiàn)和使用)一樣工作. 通過(guò)使用它可以獲得一個(gè)穩(wěn)定可靠的, 多協(xié)議的, 失敗警覺(jué)的通信.

          對(duì)我們應(yīng)用程序(dispatcher)初步建立的一個(gè)改變, 使我們從一個(gè)單一用戶界面的獨(dú)立運(yùn)行的應(yīng)用程序轉(zhuǎn)移到一個(gè)多用戶分布式的應(yīng)用程序.當(dāng)model進(jìn)入或離開(kāi)這個(gè)網(wǎng)絡(luò)(想象一個(gè)通信失敗)的時(shí)候,框架可以通知無(wú)數(shù)的監(jiān)聽(tīng)接口, 于是遠(yuǎn)程views可以采取適當(dāng)?shù)捻憫?yīng).例如,顯示一個(gè)警告信息給用戶. 這個(gè)框架也可以提供有用的methods來(lái)幫助將本地的controllers轉(zhuǎn)化成遠(yuǎn)程的.

          總結(jié)和摘要
          仍有許多元素需要被探索,就像設(shè)計(jì)controllers的方式一樣,它在目前和dispatchers具有一致的普遍性.該框架假設(shè)普通的controller-model綁定,由于前者需要知道如何去驅(qū)動(dòng)后者.未來(lái)的開(kāi)發(fā)方向?qū)⑹侵С植煌?lèi)型的views,例如使用一個(gè)Web瀏覽器, 網(wǎng)絡(luò)警覺(jué)的applets,和Java與JavaScript的通信.

          已經(jīng)討論的Stamps庫(kù)說(shuō)明如何在一個(gè)MVC架構(gòu)中降低views和models之間的耦合以及這個(gè)框架可以有效的利用Java annotations將綁定信息從實(shí)際開(kāi)發(fā)程序組件分離開(kāi).擁有隔離的綁定邏輯允許你在物理上將元件分離開(kāi)并且能提供一個(gè)本地和一個(gè)client/server結(jié)構(gòu)而不需要改變應(yīng)用邏輯或者表示層. 這些目標(biāo)提供對(duì)由一個(gè)象MVC一樣堅(jiān)固的設(shè)計(jì)模式與由annotations提供的功能強(qiáng)大的元數(shù)據(jù)結(jié)合在一起所提供的可能性的洞察.  

          關(guān)于作者
          Riccardo Govoni自從2003年開(kāi)始就做為一名J2EE的開(kāi)發(fā)者在一家位于意大利北部的金融服務(wù)公司工作.在那里,他為遺留的銀行系統(tǒng),數(shù)據(jù)庫(kù)管理,和繁重的數(shù)據(jù)處理任務(wù)開(kāi)發(fā)了許多Web前臺(tái). Govoni在J2EE多層應(yīng)用程序方面擁有豐富經(jīng)驗(yàn)并且擁有關(guān)于Java GUI 庫(kù)象Swing 和SWT詳盡的知識(shí).他擁有物理學(xué)碩士學(xué)位.在閑暇時(shí)間,Govoni在網(wǎng)絡(luò)上四處尋找最新的Java新聞,或者與朋友和(有時(shí)候)他女朋友的狗一起討論新的項(xiàng)目主意.

          資源
          ·        Stamps項(xiàng)目主頁(yè),及相關(guān)源碼文件和文檔:http://sourceforge.net/projects/stamps-mvc/
          ·        Wikipedia上關(guān)于MVC的定義:http://en.wikipedia.org/wiki/MVC
          ·        最有名的MVC實(shí)現(xiàn)之一, Struts Web 應(yīng)用框架:http://struts.apache.org/
          ·        JGoodies 綁定,一個(gè)在Swing應(yīng)用程序中解決model-view-controller綁定的不同方法:https://binding.dev.java.net/
          ·        TikeSwing, 一個(gè)基于Swing之上的開(kāi)源框架, 通過(guò)擴(kuò)展Swing widgets來(lái)引入MVC “與結(jié)合Swing來(lái)使用高層次的MVC和POJOs” Tomi Tuomainen(JavaWorld, 2005年六月):http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-tikeswing.html
          ·        Sun J2SE 5.0 annotations向?qū)?http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
          ·        J2SE 5.0 annotations 入門(mén)介紹: “Taming Tiger, 第三部分,” Tarak Modi(JavaWorld, 2004年七月):http://www.javaworld.com/javaworld/jw-07-2004/jw-0719-tiger3.html
          ·        “零距離: J2SE 5.0 Annotations,” Kyle Downey (ONJava.com, 2004年十月):http://www.onjava.com/pub/a/onjava/2004/10/06/anno1.html
          ·        JGroups, 是一個(gè)可靠的多點(diǎn)傳送通信的工具包, 在分布式Stamps MVC網(wǎng)絡(luò)中象傳輸層一樣工作:http://www.jgroups.org/javagroupsnew/docs/index.html
          ·        “一個(gè)Swing架構(gòu)的一般了解”, 作者: Amy Fowler(Sun開(kāi)發(fā)者網(wǎng)絡(luò))討論Swing’s MVC的根源:http://java.sun.com/products/jfc/tsc/articles/architecture/
          主站蜘蛛池模板: 利辛县| 嘉峪关市| 墨玉县| 温州市| 巧家县| 贡觉县| 漳平市| 名山县| 贵溪市| 威信县| 景宁| 沧源| 哈巴河县| 阿荣旗| 靖江市| 鹿邑县| 濮阳县| 锡林郭勒盟| 永州市| 开封市| 蓬莱市| 门源| 连州市| 隆安县| 白山市| 西盟| 德庆县| 阜城县| 罗甸县| 交口县| 永川市| 凤山市| 湖州市| 大埔县| 鄂托克前旗| 册亨县| 宜兰县| 孟村| 宁津县| 吴川市| 改则县|