MVC的發展與應用總結
1、 最初的程序都是是命令行界面,後來進化到GUI(Graphic User Interface),即圖形化用戶接口。以一個計算器軟件為例,一個程序無論C/S還是B/S結構都需要搞定:
a) 界面布局。整個計算器界面要怎麽布局看起來才合理、美觀。
b) 業務邏輯。例如用戶點擊“=”按鈕時,根據輸入計算輸出結果。
c) 界面交互。例如用戶點擊“=“按鈕後,界面有什麽響應,如顯示結果以及結果顯示位置等。
無MVC的情況,如winform在一個Form中,即有計算器的界面顯示代碼,也有觸發監聽器後的流程控制邏輯,還有功能邏輯計算代碼,這三者攪合在一起,程序復雜了後,代碼長度驚人,修改、擴展、閱讀他人代碼都是問題。
2、 桌面GUI程序的MVC設計模式。
符合“低耦合,高內聚“的軟件工程理念。表現在哪裏?在於MVC將界面顯示代碼跟業務邏輯代碼有效隔離,將原先糅雜一起的代碼分開,各部分趨於專門化,功能職責單一。這樣讓程序更易閱讀、維護、擴展了。
a) View:負責界面顯示。
b) Controller:負責View、Model、Service之間的交互、控制業務流程。不涉及具體的業務功能代碼。在桌面端Controller可以是組件監聽器的匿名實現類。
c) Model:簡單的數據模型,封裝View中的數據,以便於在其他層中的傳遞和使用(以對象的形式)。是數據模型,並不是業務模型,也不涉及具體的業務功能代碼。
d) Service:封裝了業務邏輯,專門實現業務功能的,如程序功能實現、數據庫操作、第三方庫調用等。在這裏專門把Service標註出來,是為了強調Model僅僅是數據模型,Controller是流程控制,他們都不含業務功能代碼,業務功能代碼集中在Service層。
桌面MVC的實現。MVC把界面顯示集中在View層,功能實現放在Service層,再在他們間封裝出Model以便數據共享,和Controller層調和各層的交互及流程控制。這樣,就實現了顯示與業務的分離。
1) View與Model應用觀察者設計模式,一方面View從Model中獲取數據渲染後呈現給用戶,另一方面當Model被修改後能自動刷新到View中並顯示出來。
2) View與Controller可以應用策咯模式,增加程序靈活性。
3) Controller組合Service(面向接口)和Model。
一個java Swing使用MVC的例子:
public abstract class View{ public void update(); } public class ViewImpl extends View{ //View的界面元素屬性。 Model model;//應用觀察者模式 Controller controller;//組合,可以用策略模式
public ViewImpl(){ model = new ModelImpl(this); controller = new Controller(model) //界面布局方法調用,初始化組件方法調用(用model中數據) }
xxx.addActionListener(new actionlistener{ @Override public void actionPerform(){ //將界面組件數據刷新到model中 controller.do1(); } })
@Override public void update(){ //更新model中的數據到View的界面組件中。 }
}
public interface Controller{ public void do1(); public void do2(); public void do3(); } public class ControllerImpl implements Controler{ Model model; public Controler(Model m){ model = m; } @Override public void do1(){ //從model對象獲取數據 //執行業務邏輯和流程 //結果更新到model ////其他一些功能調用和流程控制。 model.notifyView(); } }
public interface Model{ public void notifyView(); } public class ModelImpl{ //模型屬性等 View view; public ModelImp(View v){ view = v; } public void notifyView(){ view.update(); } }
public class Application{ public static void main(String[] args){ //用戶登陸及驗證通過後 View viewImpl = new ViewImpl(); view.visable=true; } }
目錄結構:這樣,1)符合面向接口編程(Controller和Model)和面向抽象編程(View),將設計與實現分離。2)每一個Form都由View、Controller、Model三個文件組成,功能劃分清晰,職責單一,便於開發維護。 |-Form |-View.java |-Controller.java |-Model.java |-ViewImpl_1 |-ViewImpl.java |-ControllerImpl.java |-ModelImpl.java |-ViewImpl_2 |-ViewImpl_3 |-Service |-Dao |-DBUtilies.java |-UserDao.java |-Impl |-UserDaoImpl.java |-entity |-user.java 思考:MVC只是一個設計思想,實現方式多樣。 1)上面這種方式,每一個頁面從原來的糅合一起到劃分成三個頁面,讓職責單一,便於開發維護。但很明顯額外多出很多文件出來,當程序規模不大時是否還要這樣一分為三? 2)上面View與Controller,Controller與Model他們之間是組合關系,是否可用策略模式,讓View根據不同情況使用不同Controller? 3)上面通過View的監聽器的作用只是調用Controller,真正的流程控制、功能調用在Controler中實現,可不可以直接用監聽器的匿名實現類做Controller,而減少額外的Controller文件?那麽考慮用Controller類做監聽器的實現類又如何呢? 4)創建對象的方式,是否考慮工廠設計模式,進一步解耦?還有可見性的問題,Controller只可見Model和Service,那要控制View的狀態怎麽辦,是否需要封裝其他工具類?這些問題用Spring Ioc解決怎麽樣?還有dao模塊用Mybatis怎麽樣? 5)Controller中既要處理功能調用又要處理頁面交互,一般可以單線程,先控制功能調用,調用後把結果存到Model,最後控制View顯示界面和model數據。可不可以多線程,可不可以把功能調用和頁面交互異步處理?那又是否需要同步呢? |
3、 web端程序的MVC模式。
後來B/S結構的程序開始慢慢發展,從靜態網頁到動態網頁。先說不使用MVC設計模式的情況,如java ee中,僅用jsp做開發。那麽一個jsp頁面中即有html、css、js組成的可視化界面顯示,還有流程控制代碼,以及訪問數據庫等的java程序片。為了解決開發的復雜性,同樣在B/S中使用MVC設計模式。
(典型的jsp+servlet+javaBean實現MVC)
web的MVC模式與桌面端MVC原理一樣,不過在實現上有很大不同,特別是Model層了。兩者的Model層在功能上是一樣的,都是簡單的封裝對象。
實現上,前面說過桌面端View與Model是觀察者模式,View從Model中獲取數據渲染後呈現給用戶,同時當Model被修改後能自動刷新到View中並顯示出來。而web端MVC中是依賴容器對javaBean組件的支持。jsp和Servlet中按規則使用javaBean,web容器提供一致性支持,servlet修改javaBean的屬性後,當響應用戶jsp頁面時,從javaBean組件中渲染數據到頁面並翻譯成html返回。
有兩個問題:1)、javaBean的使用方式。直接使用,jsp頁面用<jsp:UseBean />標簽,servlet用new操作符。間接使用,還可以通過內置對象Request等傳輸。這兩種方式依然歸於上面Model,因為它的本質沒變。
2)、從本文開始到現在,我還是認為MVC中的Model只是簡單的數據模型,而不是有的博客上說的jsp做界面,servlet做流程控制,javaBean處理業務邏輯。MVC本質上是為了解耦界面顯示(如jsp)與業務邏輯(如service),獨立出Controller控制流程和各層的交互,再添一個Model層解耦View和Controller。
4、 其他MVC開發框架SpringMVC
上面javaEE原生組件jsp+serlet+javaBean已經可以用MVC模式開發web程序。那為什麽大多後臺開發都用SpringMVC、Struts2這些開發框架呢?
1) javaEE原生組件雖然對程序開發提供了支持,但面對現在多變的需求,開發過程繁雜,重復代碼多。而SpringMVC等提供了封裝更好的組件與環境支持,能更快、更簡潔用於程序開發。從上面明顯看出,組件間耦合性更低了。特別是通過springMVC把View層和其他層分離,讓程序真正前後端分離了。
2) springMVC框架提供了更靈活的程序架構,更適應現在程序開發的多變。如不止可以響應用戶jsp頁面,還可以返回json、xml、excel、pdf等。
3) SpringMVC框架,還可以自由地選擇與其他框架搭配整合,如spring、mybatis等,對程序的開發提供更好的支持。
4) 框架本身,支持為特定程序架構定制組件,程序設計將有更多可能。如根據框架提供的接口,用戶可以自定義HanderAdapter、ViewResolver等組件,以此為Controller、View的變化提供支持。
5、 MVC的衍生------MVP模式
MVC有效的降低了界面顯示層與業務邏輯層的耦合性,準確的說是web端的MVC模式,對於桌面端來說,MVC實現起來有點復雜,View同時依賴Controller和Model,特別是View-Model用觀察者模式實現了。MVP由MVC演變而來,但還是有很大區別:
1) view更新方式不同。MVC中是通過策咯模式,由Model調用View的接口刷新,因此View就要依賴Model。MVP中View只依賴Presenter,由Presenter調用View的接口刷新。
2) MVC的Model是數據模型,只是簡單的數據封裝。而MVP中的Model是業務模型。此Model非彼Model,這點是最讓人迷糊的了,但要分清,所以上圖用Model(service)。
6、 MVC的衍生------MVVM模式
MVVP同樣由MVC演化而來,MVVM與MVP有點類似,不過View的刷新是通過“數據綁定”。很典型的一種實現:前端js框架VUE:
1) 通過事件驅動,把顯示層大的用戶操作傳遞到js邏輯層
2) js執行邏輯處理後,修改data域
3) data域和顯示層html是綁定了的,所以自動把結果刷新到顯示層html
7、 總結
不論桌面端還是web端,一次程序交互可以抽象為:
1)請求:桌面端通過事件監聽提交;web前端通過事件驅動提交給js邏輯層;後端通過http、https、web service等協議接受。
2)處理:控制器調用接口處理業務邏輯,以及整個操作流程的統籌控制。
3)響應:響應內容包括頁面和數據,有可能只有頁面如靜態網頁,也有可能只有數據如json。
各種模式主要區別從上面第3步總結——響應:
桌面端MVC,是用觀察者模式實現,由Model調用View的接口刷新界面。
web端MVC,是通過web容器、SpringMVC等三方庫的支持,將Modle渲染到View再返回給用戶顯示。
MVP模式,多用於桌面端或安卓等開發,由Presenter調用View的接口刷新界面。
MVVM模式,多用於web前端開發,通過數據綁定刷新頁面數據。
MVC的發展與應用總結