MVC模式在j2me項(xiàng)目中的應(yīng)用一_JSP教程
推薦:J2ME中使用記錄存儲系統(tǒng)RMS存儲信息在MIDP中,沒有文件的概念,所以永久存儲一般只能依靠記錄存儲系統(tǒng)實(shí)現(xiàn),關(guān)于記錄存儲系統(tǒng)的簡介,可以參看教程:http://www-900.ibm.com/developerWorks/cn/java/j-wi-rms/index.sht
版權(quán)聲明:本文同時(shí)發(fā)表在www.j2medev.com和我的Blog(blog.csdn.net/alikeboy)上,如果需要轉(zhuǎn)載,有三個(gè)途徑:1)聯(lián)系我并經(jīng)我同意;2)和www.j2medev.com有轉(zhuǎn)載文章合作協(xié)議的 3)通過Rss聚合我的Blog。另外網(wǎng)上轉(zhuǎn)載需要全文轉(zhuǎn)發(fā)(包括文章的頭部的聲明),不要斷章取義。
正文:
初識MVC模式第一次認(rèn)識到MVC模式是從Microsoft MFC框架所采用的“文檔-視圖”模型開始的。第一次接觸到這個(gè)概念讓我興奮不已,很長時(shí)間困擾我的程序框架問題似乎迎刃而解了。而后我翻閱了GOF一書中對MVC模式的描述,增進(jìn)了對這個(gè)模式的一些理解。應(yīng)該說MVC框架是程序設(shè)計(jì)領(lǐng)域的常青樹,也是GOF模式中最為重要的模式之一。這一經(jīng)典的模式被廣泛的使用,有太多的程序構(gòu)架在這一框架之下,從早期的卓面Application到現(xiàn)在流行的Web。并因各自的需求不同,MVC有了很多的變種。了解MVC是每個(gè)程序設(shè)計(jì)人員的必修課,最好能夠達(dá)到熟練運(yùn)用的程度。
我并不打算詳細(xì)介紹這一模式,因?yàn)榧?xì)節(jié)比較復(fù)雜,我口舌拙笨也不容易說清楚,大家應(yīng)該參閱一下有關(guān)模式的書籍,任何一本都比我要講的清楚。所以此處就一帶而過。MVC模式是Model-View-Controller的縮寫,中文譯為“模型-視圖-控制器”。MVC的核心思想是分離。Model就是對實(shí)體類的抽象;View就是Model在屏幕上的表示;Controller就是協(xié)調(diào)者�?赡苡信笥寻l(fā)現(xiàn)Controller的描述多少有些含糊,不要著急,這個(gè)一會還要談到。大概因?yàn)樘^有名,MVC模式的每個(gè)實(shí)現(xiàn)都出處很大,但他們卻都叫做MVC��!搞得初學(xué)者一頭霧水。往往濫用,最后搞得M.V.C.三者之間的協(xié)調(diào)很混亂。這其實(shí)并不是他們的錯(cuò),理清思路的關(guān)鍵還是剛剛提到的一個(gè)詞“分離”。盡管MVC實(shí)現(xiàn)不同,但是思想是一致的。
MVC模式的利與弊先談優(yōu)點(diǎn):
1)將M.V.C.分離可以讓不同的專家負(fù)責(zé)不同的模塊,一般情況下,M部分由熟悉數(shù)據(jù)庫,網(wǎng)絡(luò)傳輸?shù)膶<襾碡?fù)責(zé);V則交給對UI有研究的專家。這對于項(xiàng)目的管理者而言是多么的誘人,分工意味著可以提高效率并可以按照傳統(tǒng)的責(zé)任劃分來處理軟件開發(fā)過程。對開發(fā)者而言也可以專心于一個(gè)領(lǐng)域。這樣做的前提是接口要明確,MVC的分離思想正為其提供了基礎(chǔ)。
2)一旦V的部分發(fā)生變化,可以迅速的重構(gòu)而不必引起整個(gè)工程的返工。如今的軟件表現(xiàn)層的部分變化實(shí)在是太快了…
3)M的部分,因?yàn)樽銐虺橄螅梢苑奖愕闹貜?fù)利用,符合OO的思想。另一方面我們可以利用JUnit等單元測試工具對M進(jìn)行測試,保證工程質(zhì)量。
談完了優(yōu)點(diǎn)再來看看缺點(diǎn):
1)利用MVC模式(也包括近代的其他一些模式)暗示我們通過多產(chǎn)生一些類,來提高程序的可讀性與健壯性。附帶來的缺點(diǎn)就是類的數(shù)量的膨脹。說句笑話,MVC就好像是發(fā)面時(shí)用的速效粉一樣,是最為方便的代碼膨脹劑,相信大家都深有體會:)
2)MVC雖然定義了M.V.C.個(gè)個(gè)部件的含義,但并不具體,而且沒有非常明確的固定三者之間的聯(lián)系。所以一直以來除了View沒有爭論外,其他方面都有很多爭論,大家都想把自己的理解作為正解。尤其是“Model到底是屏幕數(shù)據(jù)的集合還是實(shí)體數(shù)據(jù)”、“控制器的作用”是兩個(gè)經(jīng)常爭論的問題。前面提過MVC變種很多,這也給初學(xué)者留下了不少的陷阱。后面結(jié)合實(shí)例將會分析幾種常見的做法。
3)MVC的實(shí)現(xiàn)成本偏高。但請注意是這是相對的,一般而言項(xiàng)目越大,越可以看出其優(yōu)勢。
常見的MVC模式實(shí)踐下面將會介紹在midp平臺幾種常見的實(shí)踐,最后是我習(xí)慣的做法
M—V形式(或者M(jìn)C—V、M—VC)
這也是在j2me中一種慣用的方法,精煉的說這種方法是以屏幕為組織單位的,因而很適合RAD工具的開發(fā)思路。一個(gè)屏幕及其控制被抽象成一個(gè)VC類,而這個(gè)類中有一個(gè)私有的Model對象來代表屏幕上要用到的數(shù)據(jù)元素。屏幕對象并不保存任何的實(shí)體數(shù)據(jù),這些數(shù)據(jù)被組織在了Model對象中。大概因?yàn)槠聊粚ο蠛苤庇^,控制器的作用也不明晰(它絕大部分的功能被view或是model取代,具體取決于你的實(shí)現(xiàn)),所以也常常稱呼為model-view模式。形式如下:
class MyFrame extend Frame{ private Model model; private StringItem name; MyFrame(Model model){ this.model=model; name=new StringItem(model.getName());//請求模型的數(shù)據(jù) append(name); } } class Model{ private String name="M-C pattern"; public String getName(){//這是一個(gè)服務(wù)接口 return name; } } |
上面看到的是個(gè)典型的M—V模型,我們可以理解這種以屏幕為核心的分離的含義。Model組織起屏幕的數(shù)據(jù),view向Model索要其希望顯示的數(shù)據(jù),注意這一操作一定要通過預(yù)先協(xié)商好的接口訪問,而不是直接操作。如果出現(xiàn)復(fù)雜的事務(wù)邏輯(用戶選擇的某種操作),有人將其放在Model端,也有人放在View端,但一般上放在Model端,這時(shí)Model帶有嚴(yán)重的Controller的色彩。
這種形式的優(yōu)點(diǎn)是非常的直觀,也有限的分離了顯示和數(shù)據(jù)。如果�?磈2medev.com站長Mingjava的文章,可以看到大部分他寫的例子都是這種模式。并且這種模式也常常用于RAD工具。
這種模式的缺點(diǎn)是它與RAD工具一樣鼓勵(lì)你從屏幕開始思考問題,這往往讓你陷入RAD的陷阱——不先考慮事務(wù)的流程,而是從用戶接口直接下手去分析問題,這往往扼殺了你的全局構(gòu)思。
Sun blueprints: Smart Ticket中使用的MVC模式
著名的藍(lán)圖程序Smart Ticket中使用了MVC模式,并且這一模式幫助Sun的程序員在MIDP2發(fā)布時(shí),快速的將Smart Ticket的view部分從MIDP1.0 更新到MIDP2.0。
Sun針對MIDP的特點(diǎn),設(shè)計(jì)并改進(jìn)了這一模式,在SUN的解決方法中是一個(gè)很標(biāo)準(zhǔn)的方法,只是 Controller變成了一個(gè)巨大的事務(wù)處理器,所有由UI對象收集到的用戶的需求都轉(zhuǎn)發(fā)給Controller處理。Controller內(nèi)部保存了一組常量。在一個(gè)dispose(int id)形式的方法里一個(gè)巨大的switch case語句根據(jù)比較不同的常量,處理不同的請求。這種技術(shù)有時(shí)也將Controller稱為處理器,或者屏幕導(dǎo)航器。這種模式的提出者主要是要集中處理j2me里頻繁的畫面導(dǎo)航。
很多人都覺得,在j2me中將Controller改造成巨大的事務(wù)處理器是一個(gè)很好的方法。我對此持保留意見。
iFeedback中簡化的MVC
為了大大減少類的數(shù)量,iFeedback的作者,將MVC封裝到一個(gè)類中,用不同的方法來代表對這三者的分離,這種舉動(dòng)證明對減少類的數(shù)量又很大幫助。
public abstract class MVCComponent implements CommandListener { // Set from outside at beginning public static Display display; // Returns the screen object from the derived class public abstract Displayable getScreen(); public Displayable prepareScreen () throws Exception { if ( getScreen() == null ) { initModel(); createView(); } else { updateView(); } getScreen().setCommandListener ( (CommandListener) this ); return getScreen (); } public void showScreen() { try { display.setCurrent( prepareScreen() ); } catch (Exception e) { e.printStackTrace(); Alert a = new Alert("Error in showing screen"); a.setTimeout(Alert.FOREVER); display.setCurrent(a); } } // Initialize. If a data member is not backed by RMS, make sure // it is uninitilzed (null) before you put in values. protected abstract void initModel () throws Exception; protected abstract void createView () throws Exception; protected abstract void updateView () throws Exception; public abstract void commandAction(Command c, Displayable s); } |
因?yàn)槎荚谝粋(gè)類里面,你在也不必被MVC三者之間的關(guān)系操心了,這種退化的做法,是對MIDP有限資源的妥協(xié)。
我的習(xí)慣做法
下面結(jié)合我對MVC的理解和大家交流一下。我使用的是一種UML標(biāo)準(zhǔn)的做法,最大程度上對的體現(xiàn)分離的思想。首先和大家交流一下詞匯表:
View代表屏幕。
View通過預(yù)先商定好的接口向Controller索要數(shù)據(jù),View同時(shí)收集用戶的輸入,View并不處理這些輸入,而是根據(jù)不同的輸入回調(diào)Controller不同的方法。通常View的子類使用UI后綴。
Controller 控制器
提供View調(diào)用的接口,負(fù)責(zé)和model交流�?刂破骱蚔iew共同擔(dān)負(fù)起和用戶交流的作用。
Model 泛指一系列的實(shí)體對象
需要注意的是我理解的Model并不是屏幕數(shù)據(jù)的組織單位。Model代表一系列的實(shí)體對象。由Controller跟Model交流。我覺得RAD工具中常常將Model代表屏幕數(shù)據(jù)的集合正式導(dǎo)致MVC概念混亂的一個(gè)原因。RAD工具中Model,大體相當(dāng)于這里的Controller所起的作用。

控制器并不總是聯(lián)系著Model,有時(shí)只是依賴關(guān)系。并且Controller往往通過Model的對應(yīng)的生命期類來獲得Model對象。在這種形式中,層層隔離,View與Controller緊密相連,而Model有很高的獨(dú)立性,可以很好的重用。
一般的結(jié)合UML設(shè)計(jì)的過程,對MVC的各個(gè)類有相應(yīng)的命名習(xí)慣。
View 稱為Boundary類(邊界類) 以UI結(jié)尾
Controller 稱為 Controller類(控制類) 以Workflow結(jié)尾
Model 稱為Entity類(實(shí)體類) 以Entity結(jié)尾或者沒有尾綴
Model對應(yīng)的Lifecycle類(生命周期類) 以Locator結(jié)尾

邊界類和控制類的基礎(chǔ)類如下
BaseView.java /** * @author Favo * * 視圖類 */ public abstract class BaseView { public abstract Display getDisplay(); /** * 簡單的返回包裝的屏幕對象,不要做任何準(zhǔn)備屏幕的操作! */ public abstract Displayable getScreen(); /** * 創(chuàng)建屏幕 */ protected abstract void createView() throws Exception; /** * 更新屏幕 */ public abstract void updateView() throws Exception; /** * 返回控制器 */ public abstract BaseController getController(); /** * 準(zhǔn)備屏幕 * 返回準(zhǔn)備好的屏幕對象 */ public Displayable prepareScreen() throws Exception { if(getScreen()==null){ createView(); } else { updateView(); } return getScreen(); } /** * 顯示當(dāng)前屏幕 */ public void displayScreen(){ try{ getDisplay().setCurrent(prepareScreen()); } catch (Exception e) { e.printStackTrace(); Alert al=new Alert("Error", e.toString() '\n' e.getMessage(),null,AlertType.ERROR); al.setTimeout(Alert.FOREVER); getDisplay().setCurrent(al); } } } BaseController.java /** * @author Favo * * 控制類 */ public abstract class BaseController { public abstract BaseView getView(); public abstract void setView(BaseView view); } |
注意到這些基礎(chǔ)的類并沒有向MFC框架那樣產(chǎn)生完整的框架,而是設(shè)計(jì)成了抽象類,一來希望強(qiáng)迫大家實(shí)現(xiàn)抽象類(防止出錯(cuò));二來希望增加一點(diǎn)靈活性。所以兩個(gè)類之間的通信就要靠大家撰寫的子類的構(gòu)造函數(shù)了。一般我的習(xí)慣是,初始化好控制器,然后將控制器作為參數(shù)傳給邊界類的構(gòu)造函數(shù),由邊界類的構(gòu)造函數(shù)來回調(diào)控制器的setView()來實(shí)現(xiàn)的。這些步驟是一定要有的,不然會NULLpointerExcpetion哦。
盡管理論上可能很清晰,但實(shí)踐帶來的復(fù)雜性是驚人的。這正是軟件開發(fā)的問題,太多的細(xì)節(jié)困擾這開發(fā)者對大局的把握。本文接下來,將結(jié)合最后這種設(shè)計(jì)思想,給出一個(gè)完整的設(shè)計(jì)實(shí)例。幫助大家從實(shí)踐的角度理解運(yùn)用這一模式。敬請大家期待。
編輯推薦:MVC模式在j2me項(xiàng)目中的應(yīng)用(二)分享:J2ME與MIDP開發(fā)1MIDP是Mobile Information Devices Profile(移動(dòng)信息設(shè)備簡表)的簡稱,而遵照 MIDP和CLDC規(guī)范編寫的 Java應(yīng)用程序我們就稱其為 MIDlet。 你可以從MIDP這個(gè)規(guī)范的英文名稱的含義推測
- jsp response.sendRedirect不跳轉(zhuǎn)的原因分析及解決
- JSP指令元素(page指令/include指令/taglib指令)復(fù)習(xí)整理
- JSP腳本元素和注釋復(fù)習(xí)總結(jié)示例
- JSP FusionCharts Free顯示圖表 具體實(shí)現(xiàn)
- 網(wǎng)頁模板:關(guān)于jsp頁面使用jstl的異常分析
- JSP頁面中文傳遞參數(shù)使用escape編碼
- 基于jsp:included的使用與jsp:param亂碼的解決方法
- Java Web項(xiàng)目中連接Access數(shù)據(jù)庫的配置方法
- JDBC連接Access數(shù)據(jù)庫的幾種方式介紹
- 網(wǎng)站圖片路徑的問題:絕對路徑/虛擬路徑
- (jsp/html)網(wǎng)頁上嵌入播放器(常用播放器代碼整理)
- jsp下顯示中文文件名及絕對路徑下的圖片解決方法
- 相關(guān)鏈接:
- 教程說明:
JSP教程-MVC模式在j2me項(xiàng)目中的應(yīng)用一
。