引子
了解設(shè)計(jì)模式的人應(yīng)該都多少聽(tīng)說(shuō)過(guò)MVC模式。
嚴(yán)格意義上來(lái)說(shuō)悯辙,“MVC模式”是一個(gè)偽概念才避,因?yàn)镸VC并不屬于設(shè)計(jì)模式,至少不屬于GoF的23種設(shè)計(jì)模式之一哺壶,而更像是一個(gè)設(shè)計(jì)模式的結(jié)合體:V和C之間會(huì)實(shí)現(xiàn)觀察者模式屋吨,M內(nèi)部會(huì)實(shí)現(xiàn)單例模式,C在派發(fā)任務(wù)時(shí)會(huì)實(shí)現(xiàn)Command模式山宾。
不得不說(shuō)至扰,MVC模式對(duì)軟件的高可擴(kuò)展性和高可維護(hù)性做出了巨大的貢獻(xiàn),這也使得MVC模式成為很多中等規(guī)模甚至大規(guī)模軟件的常用框架资锰,且經(jīng)歷了20余年仍舊在軟件開(kāi)發(fā)領(lǐng)域流行并通用敢课,足可見(jiàn)MVC模式的經(jīng)典。
但是傳統(tǒng)MVC模式真的那么完美嗎绷杜?
傳統(tǒng)MVC的痛點(diǎn)
讓我們一個(gè)個(gè)來(lái)說(shuō)直秆。
Controller:控制器,包含了項(xiàng)目的業(yè)務(wù)邏輯鞭盟。但是也是被大家吐槽最多的一個(gè)圾结,原因就是很多人,或者說(shuō)大多數(shù)人懊缺,習(xí)慣于什么都往Controller里寫(xiě)疫稿,最后一個(gè)Controller超過(guò)1000行代碼是司空見(jiàn)慣的事。所以關(guān)于傳統(tǒng)MVC的第一個(gè)痛點(diǎn)就是鹃两,Controller過(guò)于臃腫遗座。
Model:模型,包含了項(xiàng)目的數(shù)據(jù)模型俊扳。MVC定義之初途蒋,Model是核心,旨在使得同一個(gè)Model可以被復(fù)用到多個(gè)項(xiàng)目或者被復(fù)用到同一個(gè)項(xiàng)目的不同模塊之中馋记。但是在實(shí)際項(xiàng)目中号坡,Model還承載著純Model層內(nèi)部的運(yùn)算的工作懊烤,但是運(yùn)算部分會(huì)項(xiàng)目的不同而有所區(qū)別,因此與項(xiàng)目的適配反而成為了Model可復(fù)用的枷鎖宽堆。所以關(guān)于傳統(tǒng)MVC的第二個(gè)痛點(diǎn)就是腌紧,Model變得不可復(fù)用。
View:視圖畜隶,包含了項(xiàng)目所有的UI組件壁肋。視圖本身沒(méi)有什么好被大家詬病的,但是由于MVC中對(duì)于View和Controller界限的模糊界定造成了使用者在寫(xiě)代碼的時(shí)候會(huì)覺(jué)得這部分代碼放在View或者Controller里都可以的情況籽慢。例如事件的處理浸遗,組件的組合等。所以關(guān)于傳統(tǒng)MVC的第三個(gè)痛點(diǎn)就是箱亿,View概念的模糊跛锌。
PureMVC
既然上文說(shuō)的是傳統(tǒng)MVC,那么可以判定PureMVC是一個(gè)新型MVC届惋。
其實(shí)PureMVC只是相對(duì)于傳統(tǒng)MVC(20年陳釀)來(lái)說(shuō)“新”一些而已髓帽,因?yàn)镻ureMVC今年也已經(jīng)有10年的歷史了。
PureMVC是一款基于MVC的開(kāi)源框架盼樟,最初是為基于ActionScript3的Flash,RIA程序開(kāi)發(fā)的氢卡,后來(lái)被移植到16種語(yǔ)言平臺(tái)上。
PureMVC分為標(biāo)準(zhǔn)版本和多核版本晨缴,后者為程序的模塊化開(kāi)發(fā)提供了支持译秦。本文以標(biāo)準(zhǔn)版為例分析PureMVC。
PureMVC的MVC
在PureMVC實(shí)現(xiàn)的MVC模式中击碗,MVC分別由三個(gè)單例模式來(lái)管理筑悴,三者成為PureMVC的核心層。
Model與Proxy
Proxy(模式)稍途,提供了一個(gè)一個(gè)包裝器或一個(gè)中介被客戶(hù)端調(diào)用阁吝,從而達(dá)到去訪問(wèn)在場(chǎng)景背后的真實(shí)對(duì)象。Proxy模式可以方便的將操作轉(zhuǎn)給真實(shí)對(duì)象械拍,或者提供額外的邏輯突勇。
在PureMVC中,Model保存了對(duì)Proxy對(duì)象的引用坷虑,Proxy去操作具體的數(shù)據(jù)模型(Data Object)甲馋。也就是說(shuō),Proxy管理Data Object以及對(duì)Data Object的訪問(wèn)迄损。
View與Mediator
Mediator(模式)定躏,定義了一種封裝對(duì)象之間交互的中介。這種設(shè)計(jì)模式被認(rèn)為是行為模式因?yàn)樗梢愿淖兡J降倪\(yùn)行行為。
正如定義里所說(shuō)痊远,PureMVC中垮抗,View只關(guān)心UI,具體的對(duì)對(duì)象的操作由Mediator來(lái)管理碧聪,包括添加事件監(jiān)聽(tīng)冒版,發(fā)送或接受Notification,改變組件狀態(tài)等矾削。這也解決了視圖與視圖控制邏輯的分離壤玫。
Controller與Command
Command(模式),是一種行為設(shè)計(jì)模式哼凯,這種模式下所有動(dòng)作或者行為所需信息被封裝到一個(gè)對(duì)象之內(nèi)。Command模式解耦了發(fā)送者與接收者之間的聯(lián)系楚里。
在PureMVC中断部,Controller保存了所有Command的映射。Command是無(wú)狀態(tài)且惰性的班缎,只有在需要的時(shí)候才被創(chuàng)建蝴光。
Facade
與傳統(tǒng)MVC模式不用的是,PureMVC中對(duì)于Model达址,View蔑祟,Controller的調(diào)用是基于Facade模式的。
Facade模式沉唠,對(duì)應(yīng)了GoF中的Facade模式疆虚,是一種將復(fù)雜且龐大的內(nèi)部實(shí)現(xiàn)暴露為一個(gè)簡(jiǎn)單接口的設(shè)計(jì)模式,例如對(duì)大型類(lèi)庫(kù)的封裝满葛。
在PureMVC中径簿,F(xiàn)acade是與核心層(Model,View,Controller)進(jìn)行通信的唯一接口,目的是簡(jiǎn)化開(kāi)發(fā)復(fù)雜度嘀韧。實(shí)際編碼過(guò)程中篇亭,不需要手動(dòng)實(shí)現(xiàn)這三類(lèi)文件,F(xiàn)acade類(lèi)在構(gòu)造方法中已經(jīng)包含了對(duì)這三類(lèi)單例的構(gòu)造锄贷。
PureMVC各層之間的交互
View層的Mediator可以和Model層的Proxy進(jìn)行互相訪問(wèn)译蒂,但是PureMVC設(shè)計(jì)之初是希望只有View依賴(lài)于Model,反之不成立谊却。也就是View可以知道Model層有什么柔昼,但是Model層不需要知道View的任何內(nèi)容。Mediator訪問(wèn)數(shù)據(jù)可以直接通過(guò)Proxy來(lái)完成因惭,但是如果要對(duì)Proxy具體的內(nèi)容進(jìn)行加工岳锁,必須要通過(guò)Controller的Command來(lái)完成,這有助于實(shí)現(xiàn)View和Model之間的松散耦合蹦魔。
如上文所說(shuō)激率,Proxy最好不要直接調(diào)用Mediator來(lái)通知它請(qǐng)求完成咳燕,而是在異步取到數(shù)據(jù)之后,通過(guò)Notification來(lái)進(jìn)行通知乒躺。Proxy只發(fā)送通知招盲,不應(yīng)該監(jiān)聽(tīng)通知,因?yàn)镻roxy屬于Model層嘉冒,不應(yīng)該知道View層的狀態(tài)變化曹货。當(dāng)然,Proxy應(yīng)當(dāng)對(duì)外提供數(shù)據(jù)變更的接口讳推。
Command的實(shí)例化與執(zhí)行只能由Controller來(lái)做顶籽。作為控制邏輯的執(zhí)行體,Command有權(quán)拿到Proxy和Mediator的對(duì)象银觅,并進(jìn)行值加工礼饱,最后會(huì)將結(jié)果通過(guò)Notification發(fā)送給其它Command或者M(jìn)ediator。
業(yè)務(wù)邏輯 VS 域邏輯
你可能會(huì)遇到這個(gè)問(wèn)題:某段邏輯到底是應(yīng)當(dāng)放在Proxy(Model)里究驴,還是應(yīng)該放在Command(Controller)里镊绪?
其實(shí)這個(gè)問(wèn)題可以引申為業(yè)務(wù)邏輯與域邏輯的區(qū)別。
- 業(yè)務(wù)邏輯
指的是那些需要協(xié)調(diào)Model與View的邏輯洒忧。 - 域邏輯
指的是僅僅是針對(duì)數(shù)據(jù)模型的操作蝴韭,不論是對(duì)于客戶(hù)端還是對(duì)于服務(wù)端,不論是同步的操作還是異步的操作熙侍。
因此榄鉴,業(yè)務(wù)邏輯理所當(dāng)然應(yīng)該放在Command里來(lái)完成,而域邏輯應(yīng)當(dāng)放在Proxy里完成核行。
案例分析
...
總結(jié)
回到文章的開(kāi)頭牢硅,PureMVC到底如何解決了傳統(tǒng)MVC的三個(gè)痛點(diǎn)?
Controller將操作邏輯細(xì)化為Command
根據(jù)PureMVC的最佳實(shí)踐芝雪,Controller實(shí)體不需要單獨(dú)實(shí)現(xiàn)减余,且Controller內(nèi)部將每一個(gè)操作分割為一個(gè)個(gè)Command,這從根本上解決了Controller越來(lái)越臃腫的問(wèn)題惩系,強(qiáng)制用戶(hù)將Controller里每一個(gè)操作細(xì)粒度化位岔,使得代碼可讀性更強(qiáng),維護(hù)性更高堡牡。
Proxy負(fù)責(zé)域邏輯抒抬,DataObject負(fù)責(zé)數(shù)據(jù)模型
PureMVC中,與域相關(guān)的邏輯和接口由Proxy來(lái)負(fù)責(zé)晤柄,后續(xù)的添加和修改接口只在Proxy中完成擦剑。而DataObject是完全對(duì)業(yè)務(wù)進(jìn)行數(shù)據(jù)建模而產(chǎn)生的數(shù)據(jù)模型,與業(yè)務(wù)沒(méi)有絲毫的關(guān)系,因此也保證了高可移植性惠勒。
ViewComponent只關(guān)注UI赚抡,其余的交給Mediator
PureMVC規(guī)定了ViewComponent只負(fù)責(zé)UI的繪制,而其他事情纠屋,包括事件的綁定統(tǒng)統(tǒng)交給Mediator來(lái)做涂臣。這也就避免了ViewComponent內(nèi)部代碼定義模糊,更不會(huì)和Controller的代碼進(jìn)行混淆售担。
作者:nimomeng
鏈接:http://www.reibang.com/p/47deaced9eb3
來(lái)源:簡(jiǎn)書(shū)
簡(jiǎn)書(shū)著作權(quán)歸作者所有赁遗,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。