關於對MVC和MVVM的思考
前言:最近公司交給我一個web項目,其采用的框架是java中的zkoss,它不用於以往我平時用的mvc,它采用的mvvm模式,因為以前只理解過mvc,經常使用譬如SpringMvc、Struts2等框架,對於mvc模式理解的較多,而這個zkoss框架則不用,它是基於ajax的,采用的是mvvm的模式(當然它也提供了mvc的模式,若想使用也可以)。今天就想來淺談一下mvc和mvvm模式各自的優缺點和在項目中如何使用好它們。
本篇博客目錄:
一:mvc模式
二:mvvm模式
三:mvc和mvvm模式各自的優點和不足
五:總結
一:mvc模式
1.1: MVC是一種經典的軟件建造模式了,它主要分為三層,分別為Model、view、controller,其表示的含義是模型層、視圖層、控制層,其中根據這三層又可以抽象出很多層來。但是其主要的思想是變的,像我們平時使用的框架SpringMvc、struts2等都是java web中的mvc框架, 遵循了mvc的設計範式。mvc模式的入口在view上,視圖層也就是我們平時看到的網頁頁面,比如一個按鈕、一個輸入框、一個鏈接等可以看做是視圖層的一部分,然後視圖層直接和控制器打交道,一個web網站的最根本其實是實現數據的傳輸與流通,然後再把它返回給頁面。當視圖層問候控制器的時候,這個時候控制器去模型層去拿封裝好的數據模型進行數據組裝,如果涉及到數據的crud的話,我們需要再去把控制層進行再劃分,常見的比如:Service、Dao、Controller,service層主要做的是封裝業務邏輯的屬性,而Dao層就是和數據庫進行打交道了。這些再劃分最終的目的也是更好的實現業務邏輯。
1.2:舉個很簡單的例子,首先用戶通過點擊web頁面上的一個輸入框,比如我們常用是上網場景是打開百度,在百度中輸入一個關鍵字,那麽百度就會呈現出根據這個關鍵字查詢出來的結果網頁(我們要做的是把值顯示到一個p標簽裏),這其中百度網站又做了些什麽呢?百度後臺又是如何實現的呢?我們來簡單的模擬一下(當然真實的百度可能並不是這樣,這裏只是舉例說明):
<form action="search"> <input type="text" /> <input type="submit" /> </form>
<div>
<p id="p1"></p>
</div>
這是一個簡單的form表單,當用戶點擊submit按鈕的時候,這個form表單就會被提交到服務器,其中它會帶著seacrh這個action,也就是一個請求來到我們的服務器中,假如我們采用的是Springmvc框架的話,那麽此時會有一個控制器進行接收:一般的情況會如下
@Controller
public class SearchController{
@RequestMapping("search") public String doSearch(@requestParam String input,Model model){ String result=doSearchService.search(input);
model.serAttribute("userInput",result);
return "SearchRes"; }
}
這個控制器一般會映射search請求,拿到請求的參數,然後調用service進行查詢,再把結果直接返回到SearchRes視圖中,這個視圖就可以訪問model對象從而根據用戶輸入的值拿到結果返回給頁面,這其中又要用到javaScript通過異步請求ajax來把值傳遞給p標簽,改變它的innerHtml,從而完成賦值的過程。(這一步暫時省略)
二:mvvm模式
2.1:mvvm模式,望文生義,它主要分為model、view、viewModel.也就是數據模型、視圖、視圖+模型層,註意它不是四層而是三層。很多前端框架都采用了這種模式,比如:angular.js、konckoutJs等,它最大的好處就是可以實現自動綁定,將數據綁定在組件ui上,當UI中的值發生變化的時候,那麽它對應的模型中的值也跟隨發生變化,這也就是它雙向綁定機制,原因在於它在視圖層和數據模型層之間實現了一個綁定器,綁定器可以管理兩個值,它一直監聽組件UI的值,只要發生變化,它將會把值傳輸過去改變model中的值.綁定器比較靈活,還可以實現單向綁定。
2.2:我們來按照mvvm模式來仿照一下剛才的mvc結構下的搜索的例子,這裏用zkoss框架作為示範:
<textbox value="@binding(vm.UserInput)"/>
這是一個view層,zkoss采用是視圖叫做zul,這串代碼裏它有一個textbox組件,也就是一個輸入框,然後它的value值通過@binding註解綁定到viewmodel中的一個字段叫做UserInput,這個註解會自動實現當用戶輸入一個值的時候,它將會把值綁定在UserInput這個字段上,同樣在viewmodel中UserInput這個字段的值發生改變的時候,前端Ui中組件的值也同樣會跟隨發生變化。這就間接節省了很多程序員的工作,比如在Servlet中我們還需要用String uiValue=request.getParamter("userinput");才能拿到它的值。
接下來,我們需要用過這個值然後進行查詢。這裏我們就可以采用mvc模式了,把mvvm得到的值視為一個model,然後讓mvc去查詢,查詢後我們只需要把結果賦值給這個UserInput就可以了,它可以自動完成綁定,那麽我們在頁面中看到的是變化後的值。
public class SearchViewModel{
public String userInput; @RequestMapping("search") public String doSearch(@requestParam String input){ String result=doSearchService.search(input);
userInput=reslut; } }
三:mvc和mvvm模式各自的優點和不足
3.1:mvvm的優點
3.1.1:mvvm自動綁定機制可以大大減少我們寫代碼的數量,很方便,一切都趨於自動化,數據跟隨頁面UI變化。而在mvc裏面,你需要去通過方法去獲取這個組件對應的值。一定程度上減少了我們的代碼量,提高了編程效率
3.2.2:mvvm數據的一致性更高,因為在mvc模型裏,很可能出現某個組件獲取值的時候出現錯誤,而在mvvm就不存在這個問題,值和組件綁定就會保證獲取的值是可靠並且一致的
3.2.3:mvvm更便於理解,程序員的學習成本較低,(但內部封裝的比mvc模式要復雜),學習起來更簡單
3.2:mvvm的缺點
3.2.1:正所謂越自動的東西越有出錯的幾率,mvvm的自動綁定機制,偶爾會出現一種不靈活的現象,數據綁定會失靈,我就遇見過這樣的現象
3.2.2:mvvm構建的程序在vm會顯得臃腫,因為所有的邏輯都集中在vm中了,而在mvc裏面不存在這個問題。並且vm中的方法無法進行復用,你必須重新復制原來的方法屬性才可以
3.2.3:mvvm做的程序的健壯性不如mvc,mvc的靈活、操作性較強,而mvvm在遇見一些復雜的組件上,無論是靈活度還是執行性都不如mvc,這點我深有體會,在Zkoss的框架使用中,遇見一些稍微比較復雜的業務邏輯的時候,發現我用mvvm根本無法實現,不得已轉換到mvc的模式上
3.3:mvc的優點
3.3.1:mvc作為一種經典的web框架模型,它構建出的程序穩定可靠,並且具有很高的分層度,提起mvc我們經常想到的是業務層、邏輯層、Dao層,這種鮮明的分層架構給程序帶來了高度可復用的好處,並且層次清晰,便於構建大型應用程序
3.3.2:mvc對於組件的操作性更好,擅於控制各種組件,並且組織各種關系數據對其進行高度可控的封裝
3.3.3:mvc靈活度更高,對於同一個業務場景可以存在很多的實現方式,而mvvm就相對來說非常單一了
3.4:mvc的缺點
3.4.1:mvc模式要比mvvm寫更多的代碼,代碼的可讀性和便捷性上不如mvvm。
3.4.2:mvc模式一般實現起來更復雜,並沒有mvvm那麽相對來說比較輕量
3.4.3:mvc模式嚴格遵守這種模式,導致比較小的程序也得按照它的分層要求來實現,比較小的應用完全可以不采用它的分層結構(實現起來比較復雜),而他要求不論大小應用程序必須嚴格遵守分層的結構(當然任性也可以不遵守),比較微小的服務完全可以不用采用mvc模式,可以選擇mvvm更快捷方便
關於對MVC和MVVM的思考