一. MVC弹澎,MVP和MVVM誕生需求
MVC,MVP和MVVM都是用來(lái)解決界面呈現(xiàn)和邏輯代碼分離而出現(xiàn)的模式朴下。
軟件中最核心的,最基本的東西是什么苦蒿?是的殴胧,是數(shù)據(jù)。我們寫的所有代碼都是圍繞數(shù)據(jù)的產(chǎn)生佩迟,修改等變化出現(xiàn)了業(yè)務(wù)邏輯团滥。
一般的代碼結(jié)構(gòu)從上到下依次是視圖層,業(yè)務(wù)邏輯層和數(shù)據(jù)層音五,而MVC惫撰、MVP和MVVM都是來(lái)解決視圖層和業(yè)務(wù)邏輯層的耦合。
二. MVC模式
MVC全名是Model View Controller躺涝,是模型(model)-視圖(view)-控制器(controller)的縮寫厨钻。MVC開始是存在于桌面程序中,使用MVC的目的是將M和V的實(shí)現(xiàn)代碼分離坚嗜。
2.1 主動(dòng)MVC
MVC的理論思想對(duì)應(yīng)的是主動(dòng)MVC夯膀,這里的主動(dòng)的意思是Model會(huì)主動(dòng)通知View更新。而我們使用的MVC框架苍蔬,Struct诱建、asp.net mvc等都不是主動(dòng)MVC(視圖的更新都是通過(guò)Controller來(lái)完成的)。
Model
用于封裝與應(yīng)用程序的業(yè)務(wù)邏輯相關(guān)的數(shù)據(jù)以及對(duì)數(shù)據(jù)的處理方法碟绑。
模型中數(shù)據(jù)的變化一般會(huì)通過(guò)一種刷新的機(jī)制被公布俺猿。為了實(shí)現(xiàn)這種機(jī)制,那些用于監(jiān)聽(tīng)此模型的視圖必須事先在此模型上注冊(cè)格仲,從而押袍,視圖可以了解在數(shù)據(jù)模型上發(fā)生的變化。
View
視圖層負(fù)責(zé)數(shù)據(jù)的展示凯肋。
在視圖中一般沒(méi)有程序上的邏輯谊惭。為了實(shí)現(xiàn)視圖上的刷新功能,視圖需要訪問(wèn)它監(jiān)視的數(shù)據(jù)模型(Model)侮东,因此應(yīng)該事先在被它監(jiān)視的數(shù)據(jù)那里訂閱Model事件圈盔。
Controller
控制器是M和V之間的連接器,用于控制應(yīng)用程序的流程悄雅。它處理事件并做出響應(yīng)驱敲。“事件”包括用戶的行為和數(shù)據(jù)模型上的改變煤伟。
2.2 被動(dòng)MVC
下圖是被動(dòng)MVC中的流程癌佩,和主動(dòng)MVC不同之處是木缝,View沒(méi)有訂閱Model數(shù)據(jù)變化的事件,等待Model來(lái)通知需要根據(jù)新的數(shù)據(jù)來(lái)更新View围辙。在被動(dòng)MVC中我碟,Controller負(fù)責(zé)通知View,有數(shù)據(jù)變化姚建,需要更新視圖矫俺。
被動(dòng)MVC與主動(dòng)MVC的區(qū)別:
- 模型對(duì)視圖和控制器一無(wú)所知,僅僅是被他們使用
- 控制器使用視圖掸冤,并通知它更新數(shù)據(jù)顯示
- 視圖僅僅是在控制器通知它去模型取數(shù)據(jù)的時(shí)候它才這么做(視圖并不會(huì)訂閱或監(jiān)視模型的更新)
2.3 MVC優(yōu)點(diǎn)
*耦合性低
*開發(fā)速度快
*可維護(hù)性高
2.4 MVC使用的誤區(qū)
- 把Model理解成實(shí)體類(Entity)厘托,在MVC中Model應(yīng)該包含2部分功能,一部分是處理業(yè)務(wù)邏輯稿湿,一部分是提供View顯示的數(shù)據(jù)
- 把業(yè)務(wù)邏輯全部放在Controller中
這兩個(gè)誤區(qū)本質(zhì)上都是對(duì)Model的作用不明導(dǎo)致的
Model在MVC架構(gòu)中起的作用非常重要铅匹,他應(yīng)該是業(yè)務(wù)邏輯真正的實(shí)現(xiàn)層。所以Model實(shí)際上是Business Model(業(yè)務(wù)模型)饺藤,而Controller僅僅起一個(gè)“橋梁”的作用包斑,它負(fù)責(zé)把View的請(qǐng)求轉(zhuǎn)發(fā)給Model,再負(fù)責(zé)把Model處理技術(shù)的消息通知View涕俗。Controller是用來(lái)解耦View和Model的
2.5 MVC的缺點(diǎn)
完美的MVC應(yīng)用場(chǎng)景應(yīng)該是這樣的:
有個(gè)Student Model罗丰,關(guān)聯(lián)StudentListView,StudentEditView
對(duì)于StudentListView再姑,Student Model提供Student的集合數(shù)據(jù)來(lái)顯示StudentListView
對(duì)于StudentEditView萌抵,Student Model提供單個(gè)Student數(shù)據(jù)來(lái)展示StudentEditView并且響應(yīng)StudentEditView的保存操作
但是這只是完美的情況,實(shí)際應(yīng)用中元镀,在ListView上绍填,不單單顯示Student的信息,可能需要這個(gè)Student的歷史成績(jī)栖疑,家庭情況沐兰,老師信息,而這些是Student Model不能提供的
也許我們可以擴(kuò)展Student Model蔽挠,將Student Model能夠提供的信息擴(kuò)展,包含成績(jī)信息等瓜浸,這本身也可以澳淑。但是,如果Student顯示的View插佛,只是需要額外的成績(jī)信息杠巡,另一個(gè)View制式需要額外的家庭信息,Student Model是不是有些疲于奔命雇寇,你能知道還有多少個(gè)差異化的View的需求氢拥?而且讓邏輯段代碼這樣不斷的修改來(lái)適應(yīng)View 端蚌铜,好嗎?
由于MVC的設(shè)計(jì)思想是從Model出發(fā)嫩海,而沒(méi)有考慮到View端的復(fù)雜性冬殃,這樣導(dǎo)致的問(wèn)題是Model難以符合復(fù)雜多變的View端變化。
相對(duì)這點(diǎn)叁怪,MVP和MVVM就要好得多审葬。它們都獨(dú)立了Presenter和ViewModel來(lái)對(duì)應(yīng)沒(méi)個(gè)View。
原文鏈接:http://www.cnblogs.com/JustRun1983/p/3679827.html
三奕谭、MVP模式
MVP模式也是一種經(jīng)典的界面模式涣觉。MVP中的M代表Model,V是View血柳,P是Presenter官册。
3.1 MVP的思想
MVP模式在我看來(lái),是一個(gè)真正意義上的隔離View細(xì)節(jié)和復(fù)雜性的模式难捌。為什么這么說(shuō)呢膝宁?
因?yàn)樵谄渌J街蠽都代表的是UI界面,但是在MVP模式中代表的是一個(gè)接口栖榨,一個(gè)將UI界面提煉而抽象出來(lái)的接口昆汹。接口意味著任何實(shí)現(xiàn)了該接口的界面,都能夠復(fù)用已有的Presenter和Model代碼
3.2 UI界面接口化
要很好的理解MVP婴栽,就要有把UI界面接口化的能力满粗。看下面的界面中愚争,將紅色標(biāo)記的User Control抽象一下映皆,就能得到下面的接口
public interface IUserAdd
{
event EventHandler UserAddEvent;
string UserName { get; set; }
string UserAge { get; set; }
}
界面中的2個(gè)輸入框被抽象成了UserName和UserAge兩個(gè)屬性。Save按鈕的點(diǎn)擊事件被抽象成了事件UserAddEvent轰枝。winform中實(shí)現(xiàn)該接口的代碼如下:
public partial class UserAdd : UserControl, IUserAdd
{
public event EventHandler UserAddEvent;
public string UserName
{
set { this.txbName.Text = value; }
get { return this.txbName.Text; }
}
public string UserAge
{
set { this.txbAge.Text = value; }
get { return this.txbAge.Text; }
}
public UserAdd()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
if (UserAddEvent != null) UserAddEvent(this, e);
}
}
下面拿UserAge屬性來(lái)解釋一下捅彻,UI界面接口化的魔力。當(dāng)后端代碼要獲取界面上的年齡值鞍陨,就只需要get屬性步淹,要更新界面顯示的時(shí)候,就只需要set屬性诚撵。這個(gè)時(shí)候缭裆,后端代碼對(duì)于界面的操作,被抽象成了對(duì)于UserAge屬性的操作了寿烟,也就是和具體的界面顯示無(wú)關(guān)了澈驼。
3.3 Presenter-Model和View之間的橋梁
針對(duì)上面的IUserAdd,對(duì)應(yīng)的Prensenter代碼是:
public class UserAddPresenter:IPresenter
{
private readonly IUser _model;
private readonly IUserAdd _view;
private readonly ApplicationFacade _facade = ApplicationFacade.Instance; //這里的facade是Presenter之間通信用的筛武,詳細(xì)可以看完整代碼
//Presenter構(gòu)造函數(shù)中缝其,將view和model作為參數(shù)傳入
public UserAddPresenter(IUser model, IUserAdd view)
{
_model = model;
_view = view;
WireUpViewEvents();
}
private void WireUpViewEvents()
{
_view.UserAddEvent += _view_UserAdd;
}
//當(dāng)view的UserAdd事件觸發(fā)挎塌,取得UI中的數(shù)據(jù),調(diào)用model邏輯處理内边,添加新用戶榴都。
//同時(shí)發(fā)送User_ADDED消息到系統(tǒng)中(系統(tǒng)中其它UI部分接收消息,比如這里的DataGrid假残,它接收到User_ADDED之后缭贡,會(huì)刷新)
private void _view_UserAdd(object sender, EventArgs e)
{
var user = new User
{
Name = _view.UserName,
Age = Convert.ToInt32(_view.UserAge)
};
_model.AddItem(user);
_facade.SendNotification(ApplicationFacade.USER_ADDED);
}
}
3.4 MVP的代碼結(jié)構(gòu)和時(shí)序圖
這里的MVP中的代碼結(jié)構(gòu)圖和時(shí)序圖,能夠更好的幫助理解MVP模式
3.5 MVP模式總結(jié)
在MVP里辉懒,Presenter完全把Model和View進(jìn)行了分離阳惹,主要的程序邏輯在Presenter里實(shí)現(xiàn)。而且眶俩,Presenter與具體的View是沒(méi)有只直接關(guān)聯(lián)的莹汤,而是通過(guò)定義好的接口進(jìn)行交互,從而使得在變更View的時(shí)候可以保持Presenter的不變颠印,即重用纲岭!不僅如此,我們還可以編寫測(cè)試用的View线罕,模擬用戶的各種操作止潮,從而實(shí)現(xiàn)對(duì)Presenter的測(cè)試-而不需要使用自動(dòng)化的測(cè)試工具。我們甚至可以在Model和View都沒(méi)有完成的時(shí)候钞楼,就可以通過(guò)編寫Mock Object(即實(shí)現(xiàn)了Model和View的接口喇闸,但沒(méi)有具體內(nèi)容)來(lái)測(cè)試Presenter的邏輯。
MVP的優(yōu)勢(shì)
- 模擬與視圖完全分離询件,我們可以修改視圖而不影響模型
- 可以更高效的使用模型燃乍,因?yàn)樗械慕换ザ及l(fā)生在一個(gè)地方-Presenter內(nèi)部
- 我們可以將一個(gè)Presenter用于多個(gè)視圖,而不需要改變Presenter的邏輯宛琅。這個(gè)特性非常的有用刻蟹,因?yàn)橐晥D的變化總是比模型的變化頻繁。
- 如果我們把邏輯放在Presenter中嘿辟,那么我們就可以脫離用戶界面來(lái)測(cè)試這些邏輯(單元測(cè)試)
四舆瘪、MVVM模式
4.1 MVVM模式的設(shè)計(jì)思想
MVVM模式中,一個(gè)ViewModel和一個(gè)View匹配红伦,它沒(méi)有MVP中的IView接口介陶,而是完全的和View綁定,所有View中的修改變化色建,都會(huì)自動(dòng)更新到ViewModel中,同時(shí)ViewModel的任何變化也會(huì)自動(dòng)同步到View上顯示舌缤。
這種自動(dòng)同步之所以能夠的原因是ViewModel中的屬性都實(shí)現(xiàn)了observable這樣的接口箕戳,也就是說(shuō)當(dāng)使用屬性的set方法某残,都會(huì)同時(shí)觸發(fā)屬性修改的事件,使綁定的UI自動(dòng)刷新陵吸。
所以MVVM比MVP更升級(jí)一步玻墅,在MVP中,V是接口IView壮虫,解決對(duì)于界面UI的耦合澳厢;而MVVM干脆直接使用ViewModel和UI的無(wú)縫結(jié)合,ViewModel直接就能代表UI囚似。但是MVVM做到這點(diǎn)是要依賴具體的平臺(tái)和技術(shù)實(shí)現(xiàn)的剩拢,這也就是為什么ViewModel不需要實(shí)現(xiàn)接口的原因,因?yàn)閷?duì)于具體平臺(tái)和技術(shù)的依賴饶唤,本質(zhì)上使用MVVM模式就是不能替換UI的使用平臺(tái)
4.2 MVVM模式結(jié)構(gòu)圖
這里是MVVM模式的結(jié)構(gòu)圖徐伐,能夠幫助更加容易的理解MVVM模式