前言置媳,在游戲開發(fā)中于樟,經(jīng)常會(huì)聽到MVC、MVP拇囊、MVVM 這類名詞迂曲,對(duì)他們的第一印象多是為了解耦、提高擴(kuò)展性而選擇的軟件架構(gòu)模式寥袭,但分別深究它們的區(qū)別或優(yōu)缺點(diǎn)路捧,又往往不得要領(lǐng),今天筆者就基于Unity游戲開發(fā)分別對(duì)這三種軟件架構(gòu)模式進(jìn)行講解传黄。
一杰扫、MVC
1.1 歷史背景
MVC模式最早由Trygve Reenskaug在1978年提出[1],是施樂帕羅奧多研究中心(Xerox PARC)在20世紀(jì)80年代為程序語言Smalltalk發(fā)明的一種軟件架構(gòu)膘掰。MVC模式的目的是實(shí)現(xiàn)一種動(dòng)態(tài)的程序設(shè)計(jì)章姓,使后續(xù)對(duì)程序的修改和擴(kuò)展簡(jiǎn)化,并且使程序某一部分的重復(fù)利用成為可能识埋。除此之外凡伊,此模式透過對(duì)復(fù)雜度的簡(jiǎn)化,使程序結(jié)構(gòu)更加直觀窒舟。軟件系統(tǒng)透過對(duì)自身基本部分分離的同時(shí)也賦予了各個(gè)基本部分應(yīng)有的功能系忙。
1.2 MVC的目的
Unity游戲開發(fā)中使用MVC模式主要是為了應(yīng)對(duì)日益復(fù)雜的業(yè)務(wù)需求,不管是從學(xué)習(xí)成本惠豺、健壯性[1]和多人并行開發(fā)來考慮笨觅,都是非常適合的拦耐。所以MVC模式也是在游戲開發(fā)中(特別是外圍系統(tǒng))使用非常廣泛的一種架構(gòu)模式。
1.3 MVC的架構(gòu)模式
- Model - 數(shù)據(jù)層见剩,負(fù)責(zé)處理數(shù)據(jù)相關(guān)的操作杀糯。這部分多數(shù)只管能否做,而不考略是否應(yīng)該做苍苞。
- View - 視圖層固翰,用戶的界面。例如:對(duì)界面組件的持有羹呵、不含業(yè)務(wù)邏輯的開關(guān)等操作骂际。
- Controller- 控制層,業(yè)務(wù)邏輯所在的層級(jí)冈欢。這部分是判斷是否應(yīng)該做歉铝、如何做的地方。
1.4 MVC的架構(gòu)示例圖
它們的依賴關(guān)系或數(shù)據(jù)的走向常規(guī)有以下3種凑耻,而第三種也是使用最頻繁的一種(其實(shí)項(xiàng)目中多數(shù)是使用第三種的變種)
1.5 示例圖解析
示例圖【一】
View層接收到用戶的輸入太示,將接收到數(shù)據(jù)信息推送到Controller層,Controller層收到View的數(shù)據(jù)香浩,進(jìn)行下一步的解析和整合类缤,將整合好的數(shù)據(jù)在推送到Model層,Model層接收到Contoller層整合后的數(shù)據(jù)邻吭,如果需要更新View層(界面)餐弱,就會(huì)向View發(fā)送消息通知更新界面。
示例圖【二】
與示視圖【一】最大的區(qū)別就是數(shù)據(jù)的流向都是是雙向的囱晴「囹荆基于第一張圖的說明補(bǔ)充為什么是雙向的。
-
View層為什么會(huì)直接到Model層?
因?yàn)橛幸恍┙缑娈a(chǎn)生的數(shù)據(jù)是不需要Controller層進(jìn)行解析或整合畸写,可以直接被Model層所使用降允。例如基于分析用戶行為的打點(diǎn),其實(shí)只是向數(shù)據(jù)庫(kù)發(fā)送是否點(diǎn)擊艺糜,沒有其他的業(yè)務(wù)邏輯,所以理論上可以直接發(fā)送到Model層幢尚。 -
Controller層為什么會(huì)直接到View層?
因?yàn)橐恍┎僮鞑簧婕癕odel層破停,僅僅是表現(xiàn)上的差異,所以Controller層就可以直接操作View層來控制表現(xiàn)上的差異尉剩。例如:不需要同步配置的裝飾性UI,圣誕節(jié)雪花、萬圣節(jié)偶爾飛過的蝙蝠等等继低。 -
Model層為什么會(huì)直接到Controller層?
因?yàn)镸odel層所發(fā)出的所有數(shù)據(jù)并不是都可以被View直接使用的,需要二次的解析或整合成可用的數(shù)據(jù)管嬉,然后再由Controller層推送的View層。例如:Model層下發(fā)一個(gè)用戶設(shè)置的數(shù)據(jù)結(jié)構(gòu)朗鸠,里面有聲音蚯撩、畫質(zhì)、各種偏好等等都在一個(gè)數(shù)據(jù)結(jié)構(gòu)中烛占,這個(gè)時(shí)候就需要發(fā)送到Controller層進(jìn)行解析胎挎,然后根據(jù)解析的內(nèi)容分別推送到View層。
示例圖【三】
與示例圖【二】的區(qū)別是斷開的了View層到Model層方向的連接忆家,這么做的主要目的是提高各個(gè)層級(jí)的內(nèi)聚性犹菇,尤其是提高Controller層的內(nèi)聚性,更好的控制數(shù)據(jù)的流向與業(yè)務(wù)邏輯的管理芽卿。
對(duì)于MVC模式的運(yùn)用沒有絕對(duì)的標(biāo)準(zhǔn)揭芍,在WPF、Web卸例、IOS称杨、Android、Unity開發(fā)都有各自演變币厕,其不變得主旨是對(duì)于 數(shù)據(jù)-視圖-控制 三方面的解耦列另,提高各自的內(nèi)聚性,從而達(dá)到進(jìn)一步提高健壯性[1] 的效果旦装。
1.6 MVC的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 分為職責(zé)更清晰的Model页衙、View、Controller三層阴绢,更符合高內(nèi)聚低耦合的原則店乐。
- 利于需求的變動(dòng),維護(hù)成本降低呻袭。
缺點(diǎn)
- Model層和View的聯(lián)系增加了數(shù)據(jù)流向的選擇眨八,其結(jié)果就是造成維護(hù)數(shù)據(jù)流向成本的提高,更容易出錯(cuò)左电。*
- Controller層會(huì)隨著View復(fù)雜度的增加而變得異常龐大廉侧,所以需要拆分為多個(gè)子Controller。
二篓足、MVP
2.1 歷史背景
Model-view-presenter段誊,簡(jiǎn)稱MVP,是電腦軟件設(shè)計(jì)工程中一種對(duì)針對(duì)MVC模式栈拖,再審議后所延伸提出的一種軟件設(shè)計(jì)模式连舍。
Model-View-Presenter (MVP) 是用戶界面設(shè)計(jì)模式的一種,被廣泛用于便捷自動(dòng)化單元測(cè)試和在呈現(xiàn)邏輯中改良分離關(guān)注點(diǎn)(separation of concerns)涩哟。
2.2 MVP的目的
基于MVC的普及性和成功使用的案例索赏,進(jìn)一步優(yōu)化而得到的產(chǎn)物盼玄。在原有的MVC模式的基礎(chǔ)上切斷了View層和Model層的聯(lián)系,著重關(guān)注Presenter/Controller層潜腻,也進(jìn)一步提高了Presenter/Controller層的控制權(quán)限埃儿。
2.3 MVP的架構(gòu)模式
- Model 定義用戶界面所需要被顯示的資料模型,一個(gè)模型包含著相關(guān)的業(yè)務(wù)邏輯(在實(shí)際開發(fā)中砾赔,數(shù)據(jù)相關(guān)的業(yè)務(wù)邏輯都會(huì)放到服務(wù)器)蝌箍。
- View 視圖為呈現(xiàn)用戶界面的終端,用以表現(xiàn)來自 Model 的資料暴心,和用戶命令路由再經(jīng)過 Presenter 對(duì)事件處理后的資料妓盲。
- Presenter 包含著組件的事件處理,負(fù)責(zé)檢索 Model 獲取資料专普,和將獲取的資料經(jīng)過格式轉(zhuǎn)換與 View 進(jìn)行溝通悯衬。
2.4 MVP的架構(gòu)示例圖
它們的依賴關(guān)系或數(shù)據(jù)的走向常規(guī)有以下2種,這兩種也是在實(shí)際開發(fā)中使用的方式檀夹。
MVP與MVC最大的區(qū)別是切斷了View層和Model層的聯(lián)系筋粗,View和Model上的變動(dòng)全部經(jīng)由Presenter層處理和中轉(zhuǎn)。
2.5 示例圖解析
示例圖【一】
這種方式可以算是在開發(fā)中使用頻率最高的了(因?yàn)閘ua的緣故)炸渡,在開發(fā)中通常會(huì)在對(duì)應(yīng)的Prefab上添加對(duì)應(yīng)的UINodeReference[2]組件來收集對(duì)應(yīng)的節(jié)點(diǎn)或者組件娜亿,然后通過Presenter層持有UINodeReference組件來達(dá)到控制的目的。View層產(chǎn)生的數(shù)據(jù)都會(huì)經(jīng)過Presenter層處理并推送到Model層蚌堵,Model反之如此买决。這樣對(duì)于數(shù)據(jù)的流向、控制更集中吼畏,提高了View的利用率督赤。例如View中的界面重新設(shè)計(jì),只要UINodeReference組件中的節(jié)點(diǎn)不變泻蚊,View層的替換不會(huì)影響Presenter層的使用躲舌。
示例圖【二】
這種方式是筆者最為推薦的,但是基于實(shí)際開發(fā)中使用Lua熱更的特點(diǎn)(語法和編輯器都不如C#友好)性雄,并不能得到很好的應(yīng)用没卸。此方式將View層再次拆分為View層和Controller層,View層和Controller層依靠Target–Action模式進(jìn)行關(guān)聯(lián)秒旋。此模式筆者在Unity 之 經(jīng)典優(yōu)秀框架 PureMVC(4.1.0版本)解析中對(duì)于Panel和Mediator的關(guān)聯(lián)有過應(yīng)用约计。它最大的特點(diǎn)是將純UI和對(duì)應(yīng)的UI事件進(jìn)行再次分離達(dá)到解耦的目的。
2.6 MVP的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 基于MVC的改良滩褥,含有MVC的優(yōu)點(diǎn)。
- 降低Model層和View的聯(lián)系炫加,使數(shù)據(jù)流向更可控瑰煎。
缺點(diǎn)
- Presenter/Controller層的負(fù)擔(dān)再次加重铺然,會(huì)隨著View復(fù)雜度的增加比MVC變的更加龐大,需要拆分為多個(gè)子Presenter酒甸。
三魄健、MVVM
3.1 歷史背景
MVVM(Model–view–viewmodel)是一種軟件架構(gòu)模式。
MVVM是馬丁·福勒的PM(Presentation Model)設(shè)計(jì)模式的變體插勤。[2][3] MVVM以相同的方式抽象出視圖的狀態(tài)和行為沽瘦,[3] 但PM以不依賴于特定用戶界面平臺(tái)的方式抽象出視圖(創(chuàng)建了視圖模型)。MVVM和PM都來自MVC模式农尖。
MVVM由微軟架構(gòu)師Ken Cooper和Ted Peters開發(fā)析恋,通過利用WPF(微軟.NET圖形系統(tǒng))和Silverlight(WPF的互聯(lián)網(wǎng)應(yīng)用派生品)的特性來簡(jiǎn)化用戶界面的事件驅(qū)動(dòng)程序設(shè)計(jì)。[3] 微軟的WPF和Silverlight架構(gòu)師之一John Gossman于2005年在他的博客上發(fā)表了MVVM盛卡。
MVVM也被稱為model-view-binder助隧,特別是在不涉及.NET平臺(tái)的實(shí)現(xiàn)中。ZK(Java寫的一個(gè)Web應(yīng)用框架)和KnockoutJS(一個(gè)JavaScript庫(kù))使用model-view-binder滑沧。[3][4][5]
3.2 MVVM的目的
將原來的Presenter/Controller替換為現(xiàn)在ViewModel并村,更改了原來的數(shù)據(jù)更新方式,將View和ViewModel進(jìn)行雙向綁定(data-binding)滓技,當(dāng)View中指定的數(shù)據(jù)更改時(shí)自動(dòng)更新到View層哩牍,反之View層中的數(shù)據(jù)有變動(dòng),也會(huì)自動(dòng)推送到ViewModel層令漂,MVVM與MVC/MVP最大的改變就是數(shù)據(jù)變更后自動(dòng)觸發(fā)更新事件膝昆。
3.3 MVVM的架構(gòu)模式
- Model 定義用戶界面所需要被顯示的資料模型,一個(gè)模型包含著相關(guān)的業(yè)務(wù)邏輯(在實(shí)際開發(fā)中洗显,數(shù)據(jù)相關(guān)的業(yè)務(wù)邏輯都會(huì)放到服務(wù)器)外潜。
- View 視圖為呈現(xiàn)用戶界面的終端,用以表現(xiàn)來自 Model 的資料挠唆,和用戶命令路由再經(jīng)過 Presenter 對(duì)事件處理后的資料处窥。
- ViewModel 在原有Controller層的基礎(chǔ)上,將業(yè)務(wù)邏輯封和組件進(jìn)行雙向綁定(data-binding)玄组,達(dá)到同步更新的目的滔驾。
3.4 MVVM的架構(gòu)示例圖
3.5 解析
MVVM模式在實(shí)際開發(fā)中應(yīng)用的范圍不多,在筆者的過往經(jīng)歷中俄讹,以MVVM模式為主力的開發(fā)幾乎沒有哆致,不僅僅是學(xué)習(xí)和維護(hù)的成本,而且在以Lua熱更為主流的今天患膛,采用雙向綁定這種策略對(duì)于lua來說更是難上加難摊阀,例如下面一個(gè)簡(jiǎn)單的泛型綁定類BindableProperty
,如果用lua來達(dá)到同樣簡(jiǎn)單的實(shí)現(xiàn)效果,本身就是一個(gè)難題胞此。
對(duì)這種模式也有來自MVVM的創(chuàng)造者John Gossman本人的批評(píng)臣咖,[13]他指出,實(shí)現(xiàn)MVVM的開銷對(duì)于簡(jiǎn)單的UI操作是“過度的”漱牵。他說夺蛇,對(duì)于更大的應(yīng)用來說,推廣ViewModel變得更加困難酣胀。而且刁赦,他說明了非常大的應(yīng)用程序中的數(shù)據(jù)綁定會(huì)導(dǎo)致相當(dāng)大的內(nèi)存消耗。
public class BindableProperty<T>
{
public Action<T, T> OnValueChanged;
private T _value;
public T Value
{
get
{
return _value;
}
set
{
if (!Equals(_value, value))
{
T old = _value;
_value = value;
ValueChanged(old, _value);
}
}
}
private void ValueChanged(T oldValue, T newValue)
{
OnValueChanged?.Invoke(oldValue, newValue);
}
public override string ToString()
{
return (Value != null ? Value.ToString() : "null");
}
}
3.6 MVVM的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 基于MVP的改良闻镶,含有MVP的優(yōu)點(diǎn)
- 增加了雙向綁定(data-binding)等操作甚脉,使數(shù)據(jù)推送/更新等操作更自動(dòng)化。
缺點(diǎn)
- ViewModel層的膨脹的問題依然沒有得到解決儒溉,只能拆分為多個(gè)子ViewModel宦焦。
- 非常依賴語言的特性和使用的環(huán)境(WPF),對(duì)一些動(dòng)態(tài)語言如Lua不是很友好顿涣。
總結(jié)
隨著界面復(fù)雜度的增加波闹,架構(gòu)的不同變種也在應(yīng)運(yùn)而生,從MVC--MVP--MVVM的發(fā)展我們可以看出涛碑,都是基于現(xiàn)有使用環(huán)境的情況下精堕,在原來的優(yōu)點(diǎn)上進(jìn)行優(yōu)化,所以說對(duì)于MVC/MVP/MVVM三者并沒有絕對(duì)銀彈蒲障。希望這篇文章能夠幫到你或者給予一些啟示歹篓,找到適合自己的MV*,找到自己的銀彈。
有補(bǔ)充或者更好的想法歡迎給我留言揉阎。
如發(fā)現(xiàn)不正確或者不準(zhǔn)確的地方化歡迎留言指正庄撮。
參考鏈接:
- MVC維基百科
- MVP維基百科
- MVP百度百科
- MVVM維基百科
- MVC,MVP 和 MVVM 的圖示
- MVVM模式及與MVP和MVC的區(qū)別
- MVC/MVP/MVVM/MVPVM區(qū)別
- MVC和MVVM詳解
- MVC毙籽、MVP洞斯、MVVM三種區(qū)別及適用場(chǎng)合
- 淺談 MVC、MVP 和 MVVM 架構(gòu)模式
- MVP架構(gòu)模式詳解
- MVC歷史演化
- 架構(gòu)設(shè)計(jì)的歷史·MVC·MVP·MVVM
- WPF 應(yīng)用程序使用程序的模型視圖 ViewModel 設(shè)計(jì)模式
-
健壯性(魯棒性)和可靠性是有區(qū)別的坑赡,兩者對(duì)應(yīng)的英文單詞分別是robustness 和 reliability烙如。健壯性主要描述一個(gè)系統(tǒng)對(duì)于參數(shù)變化的不敏感性,而可靠性主要描述一個(gè)系統(tǒng)的正確性毅否,也就是在你固定提供一個(gè)參數(shù)時(shí)亚铁,他應(yīng)該產(chǎn)生穩(wěn)定性的、能預(yù)測(cè)的輸出螟加。例如一個(gè)程序徘溢,他的設(shè)計(jì)目標(biāo)是獲取一個(gè)參數(shù)并輸出一個(gè)值吞琐。假如他能正確完成這個(gè)目標(biāo),就說他是可靠的然爆。但在這個(gè)程序執(zhí)行完畢后顽分,假如沒有正確的釋放內(nèi)存,或者說系統(tǒng)沒有自動(dòng)幫它釋放占用的資源施蜜,就認(rèn)為這個(gè)程序及其“運(yùn)行時(shí)”不具健壯性或者魯棒性〈朴纾【CLR Via C#】 P357 ? ?
-
泛指掛在Prefab上的Mono腳本翻默,此腳本的public 變量為需要業(yè)務(wù)邏輯控制的UI節(jié)點(diǎn)。 ?