系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之表現(xiàn)層
一、前言
最近也許是由于假期的原因,我發(fā)布的文章的速度變慢了,對(duì)大家說(shuō)下抱歉,這個(gè)系列的確我很難寫(xiě),感謝大家對(duì)我的支持和關(guān)注,的確我在發(fā)布后得到大家的支
持和認(rèn)可,讓我有了更多的動(dòng)力,之前發(fā)布的有些內(nèi)容,可能對(duì)各層講解的內(nèi)容的廣度還不夠,當(dāng)然這和我個(gè)人的水平面有關(guān),還請(qǐng)各位多多提出寶貴意見(jiàn)和建議。
從本篇開(kāi)始,我將會(huì)采用更加規(guī)范的格式,更嚴(yán)謹(jǐn)?shù)那笾獞B(tài)度,更加準(zhǔn)確的表達(dá),去將接下來(lái)的系列文章寫(xiě)完,并且與群中的很多朋友交流后,他們希望出一個(gè)總
的PDF電子書(shū),這樣可以方便閱讀,的確謝謝各位的支持,我目前將以后每篇寫(xiě)的內(nèi)容,放一份PDF格式的在群共享中,有需要的朋友可以進(jìn)行相應(yīng)的下載,由于本人
的寫(xiě)作水平有限,所以在書(shū)寫(xiě)的深度和書(shū)寫(xiě)的格式上還有很多的缺點(diǎn),還希望大家多多指出。
二、開(kāi)篇
本篇我們將針對(duì)系統(tǒng)架構(gòu)分層中的表現(xiàn)層進(jìn)行講述,分析表現(xiàn)層的架構(gòu)與設(shè)計(jì)模式,當(dāng)然我們會(huì)結(jié)合目前比較流行的表現(xiàn)層模式進(jìn)行分析講解,主要是圍繞MVC模
式的起源及發(fā)展的過(guò)程進(jìn)行講述,并且分析目前MVC模式在不同UI層中的應(yīng)用設(shè)計(jì),由于本人的水平有限,加之實(shí)際的項(xiàng)目中可能應(yīng)用的理解和經(jīng)驗(yàn)水平不足,可能在
某些分析的地方不對(duì),還請(qǐng)大家提出。我們之前的寫(xiě)作慣例,我們先來(lái)看看本文的主要講述的內(nèi)容吧

本文將會(huì)以上面的2點(diǎn)為主線展開(kāi)去講解表現(xiàn)層的內(nèi)容。
三、內(nèi)容提要
1、前言
2、內(nèi)容提要
3、本文提綱
4、表現(xiàn)層模式
4.1、表現(xiàn)層的職責(zé)
4.2、UI層與表現(xiàn)層邏輯
4.2.1、用戶界面的職責(zé)
4.2.2、表現(xiàn)層中容易產(chǎn)生的誤區(qū)
4.3、MVC模式的提出及演化
4.3.1、MVC模式
4.3.2、MVP模式
4.3.3、MVC模式與MVP模式的對(duì)比和總結(jié)
5、結(jié)束語(yǔ)
6、系列進(jìn)度
7、下篇預(yù)告
四、表現(xiàn)層模式
4.1、表現(xiàn)層的職責(zé)
我們知道任何一個(gè)應(yīng)用程序,如果想要更好的與客戶交互,我們一般都是通過(guò)提供一個(gè)用戶界面去完成與用戶的交互,當(dāng)然通過(guò)前面我們講述的,服務(wù)層與業(yè)務(wù)邏
輯層的講解,其實(shí)都是為了更好的為表現(xiàn)層服務(wù)的,通常,我們都不是特別的重視表現(xiàn)層,但是其實(shí),表現(xiàn)層同樣重要。其實(shí)通常我們?cè)陉P(guān)注各個(gè)分層的時(shí)候,我們對(duì)
每個(gè)分層的重視程度會(huì)不同,可能是由于我們自身的愛(ài)好,態(tài)度,或者是專業(yè)技能所決定的,但是一個(gè)好的系統(tǒng),必然要求我們不管哪個(gè)分層都要足夠的重視。
我們?cè)谧霰憩F(xiàn)層時(shí),通常我們會(huì)關(guān)注下面幾個(gè)組件,首先是用戶界面。也就是客戶能夠看到的用戶界面簡(jiǎn)稱UI,還有一部分就是與用戶行為進(jìn)行交互的組件,通常
我們叫做表現(xiàn)層邏輯,用戶的所有操作都通過(guò)表現(xiàn)層邏輯來(lái)支持,表現(xiàn)邏輯層將負(fù)責(zé)其他層與UI層之間的交互。
根據(jù)我們前面講述的各分層的設(shè)計(jì)我們知道,表現(xiàn)層邏輯將主要與服務(wù)層或者業(yè)務(wù)邏輯層進(jìn)行交互。具體的關(guān)系如下:

通過(guò)上圖我們知道表現(xiàn)邏輯層的位置,可以說(shuō)如何組織好用戶界面及表現(xiàn)層邏輯同其他層之間的關(guān)系,就是決定設(shè)計(jì)好壞的關(guān)鍵。也可以說(shuō)表現(xiàn)層邏輯決定了用戶
與系統(tǒng)交互。
下面我們來(lái)先看看表現(xiàn)層的職責(zé)吧
我們一般都把如下職責(zé)看作是表現(xiàn)層的職責(zé),是不是你也有相同的看法?

其實(shí),像圖中說(shuō)的驗(yàn)證,格式化,添加樣式等這些更應(yīng)該屬于UI層組件,而不應(yīng)該屬于表現(xiàn)層,但
是作為架構(gòu)師,你必須考慮的更全面,從更高的層次去考慮,比如說(shuō)下面的幾個(gè)方面:

只有更好的考慮這些因素,才能決定表現(xiàn)層的架構(gòu),我們針對(duì)上面的幾個(gè)方面來(lái)
簡(jiǎn)單的分析一下。
1、UI的無(wú)關(guān)性:
這里的UI的無(wú)關(guān)性就是指不依賴UI層的實(shí)現(xiàn)技術(shù),不管是上面說(shuō)的Web還是Winform,還是其他的WPF、WP還是其他的任何UI表現(xiàn)形式。我們知道這樣的表現(xiàn)
層設(shè)計(jì)出來(lái)是理想的,我們只是想盡可能的提高可復(fù)用性,我們希望的是雖然不同的UI使用的實(shí)現(xiàn)技術(shù)不同,但是這些UI能夠共用表現(xiàn)層邏輯,這時(shí)候我們就能做到很
好的復(fù)用性。
我們需要知道,這里提出的代碼重用只是說(shuō)是盡可能大的做到表現(xiàn)層邏輯重用,但是有些情況我們沒(méi)有辦法做到,例如Silverlight與WPF,由于他們使用不同的
CLR,所以我們只能說(shuō)是做到代碼重用,我們需要針對(duì)他們各自進(jìn)行單獨(dú)的編譯。
2、可測(cè)試性
任何分層都需要能夠測(cè)試,因?yàn)橹挥袦y(cè)試才能知道功能是否能夠很好的滿足需求。但是通常來(lái)說(shuō)表現(xiàn)層的測(cè)試,相比其他分層要復(fù)雜一些,因?yàn)楸憩F(xiàn)層需要考慮的
因素很多,所以決定了測(cè)試的難度,所以更好的測(cè)試性就是我們架構(gòu)設(shè)計(jì)的基本要求。
一般來(lái)說(shuō)我們?cè)诒憩F(xiàn)層的處理流程是這樣的:

上面的圖中大概描述了,我們?cè)诒憩F(xiàn)層中的基本流程,我們來(lái)結(jié)合圖形來(lái)說(shuō)明下:用戶界面通過(guò)用戶
操作,將觸發(fā)相應(yīng)的行為事件,這些事件將會(huì)被某個(gè)特殊的控制器進(jìn)行處理,控制器通過(guò)發(fā)送給指定的處理函數(shù),然后將處理函數(shù)返回的結(jié)果,反饋給用戶界面。
通過(guò)上面的流程我們知道,我們測(cè)試時(shí)必須模擬用戶的行為,并且如何保證用戶的行為事件能夠得到正確的處理,這些都是我們必須測(cè)試的內(nèi)容。我們?nèi)绻麑⑺?/p>
的內(nèi)容都寫(xiě)在表現(xiàn)層,那么我想可能測(cè)試起來(lái)不會(huì)那么容易,如果說(shuō)我們的用戶界面與表現(xiàn)層邏輯寫(xiě)在一個(gè)頁(yè)面中,可能我們并不容易測(cè)試,幸好APS.NET中通過(guò)代碼
后置的技術(shù),實(shí)現(xiàn)設(shè)計(jì)層與表現(xiàn)層邏輯代碼的分離。當(dāng)然我們?cè)谥熬蛯?duì)架構(gòu)設(shè)計(jì)的實(shí)現(xiàn)提出了一個(gè)觀點(diǎn),就是分離功能點(diǎn),將關(guān)注的功能點(diǎn)進(jìn)行分離,提出更高的抽
象,這樣可以達(dá)到更好的測(cè)試的目的。
3、不依賴數(shù)據(jù)模型
在服務(wù)層、業(yè)務(wù)邏輯層中我們都提到了數(shù)據(jù)傳輸對(duì)象,并且把這個(gè)對(duì)象作為與表現(xiàn)層通信的載體,使用了數(shù)據(jù)傳輸對(duì)象后,那么我們就可以做到表現(xiàn)層不依賴于我
們的數(shù)據(jù)模型,但是我們也講過(guò),數(shù)據(jù)傳輸對(duì)象為項(xiàng)目帶來(lái)了更多的類,更多的工程文件,所以這會(huì)對(duì)我們的開(kāi)發(fā)工作帶來(lái)額外的工作量。因?yàn)椴煌谋憩F(xiàn)層需要一個(gè)
與之對(duì)應(yīng)的數(shù)據(jù)傳輸對(duì)象,這些都和前面我們介紹的情況是一致的。因此,我們?cè)陧?xiàng)目中是否使用數(shù)據(jù)傳輸對(duì)象,我們需要根據(jù)項(xiàng)目的需要來(lái)決定。
4、不依賴圖形化元素
我們這里的圖形化元素是指,開(kāi)發(fā)工具給我們提供的控件和工具集合,我們通過(guò)這些圖形化元素設(shè)計(jì)出與用戶交互的界面,我們希望我們的表現(xiàn)層能夠在不同的控
件上可以以不同的方式表現(xiàn)出來(lái),我們同時(shí)希望圖形化元素中的任意修改不會(huì)影響到表現(xiàn)層邏輯,舉個(gè)例子,我們平時(shí)在博客園中的模板設(shè)計(jì),其實(shí)就是個(gè)很好的例
子,我們選擇不同的模板,我們的博客頁(yè)面就會(huì)在皮膚,樣式,主題等方面都發(fā)生變化,但是并不影響我們的表現(xiàn)層。
4.2、UI層與表現(xiàn)層邏輯
4.2.1、用戶界面的職責(zé)
我們接下來(lái)看看UI層的相關(guān)職責(zé),我們知道,我們平時(shí)在系統(tǒng)設(shè)計(jì)過(guò)程中,一般架構(gòu)師不會(huì)直接參與到用戶的界面的設(shè)計(jì)中,架構(gòu)師更側(cè)重系統(tǒng)的可用性和可訪問(wèn)
性。我們認(rèn)為UI層的主要功能包括下面幾項(xiàng):

下面我們來(lái)分別說(shuō)說(shuō)吧
1、數(shù)據(jù)顯示
我們都知道UI層是用戶使用系統(tǒng)的唯一入口,那么首先用戶界面必須將系統(tǒng)中的一些信息進(jìn)行展示,這些信息可能包括,普通信息、提示信息、系統(tǒng)中的相關(guān)數(shù)據(jù)
信息等,良好的設(shè)計(jì)UI能夠很好的展示數(shù)據(jù),用戶界面需要支持本地化及全球化功能。
2、友好的交互
交互就體現(xiàn)在用戶使用系統(tǒng)的功能,這樣就會(huì)有這樣的操作,用戶輸入相應(yīng)的數(shù)據(jù),通常來(lái)說(shuō)一個(gè)好的UI層,會(huì)提供給用戶一個(gè)比較人性化的輸入頁(yè)面,并且會(huì)根
據(jù)用戶的輸入,返回用戶想得到的結(jié)果。不管UI層的具體技術(shù)是什么,好的用戶交互頁(yè)面都是系統(tǒng)中最重要的部分。輸入的數(shù)據(jù)我們?nèi)绾巫龅桨踩苑矫娴尿?yàn)證,是我
們必須重視的部分。
3、總體外觀
系統(tǒng)的功能都是通過(guò)用戶界面來(lái)作為統(tǒng)一入口,提供給用戶使用的,所以一般來(lái)說(shuō)我們?cè)谠O(shè)計(jì)UI時(shí)必須要有精致的用戶界面,軟件的目的就是抓住用戶,能夠給用
戶較好的用戶體驗(yàn),而且根據(jù)軟件的用戶群來(lái)進(jìn)行不同的設(shè)計(jì),如果是提供給大眾使用的軟件,那么我們必須達(dá)到設(shè)計(jì)精致的用戶界面的要求,如果是提供給企業(yè)內(nèi)部
使用,那么我們可以注重功能而不是視覺(jué)效果的震撼,當(dāng)然不是說(shuō)不重視UI,只是沒(méi)有那么重視。
4.2.2、表現(xiàn)層中容易產(chǎn)生的誤區(qū)
我們來(lái)看看我們平時(shí)在表現(xiàn)層的設(shè)計(jì)與實(shí)現(xiàn)過(guò)程中可能存在的誤區(qū)吧

我們來(lái)看看每個(gè)誤區(qū)的說(shuō)明吧
1、過(guò)度依賴工具
自從有了Visual Studio 開(kāi)發(fā)工具以來(lái),就因?yàn)槠涮峁┝舜罅康目丶?,為我們開(kāi)發(fā)簡(jiǎn)單的應(yīng)用程序提供了很大的方便,我們通常都是通過(guò)拖拽控件來(lái)完成UI層的設(shè)
計(jì)。我們通過(guò)一些帶有事件的控件,去完成與其他層之間的交互,我們可以在事件中直接處理邏輯,而且很方便很快捷。這也使得我們的開(kāi)發(fā)效率很高,當(dāng)然這是開(kāi)發(fā)
簡(jiǎn)單的應(yīng)用程序時(shí)我們通過(guò)這樣來(lái)做,沒(méi)有什么問(wèn)題。但是,當(dāng)我們開(kāi)發(fā)大型的企業(yè)級(jí)應(yīng)用時(shí),這樣的方式可能就不是理想的選擇了,為什么這么說(shuō)呢?我們不是說(shuō)不
用開(kāi)發(fā)工具提供的控件,而是應(yīng)該將職責(zé)進(jìn)行劃分,比如說(shuō),用設(shè)計(jì)器完成界面的設(shè)計(jì),然后其他的代碼都是通過(guò)我們的手工邊寫(xiě),而不是通過(guò)開(kāi)發(fā)工具提供的一些控
件去完成,比如說(shuō)Visio Studio 提供的數(shù)據(jù)源綁定控件等,而且如何將事件中的代碼進(jìn)行更好的抽象就是我們這里的需要考慮的問(wèn)題。
2、表現(xiàn)層的邊界
我們先要清楚表現(xiàn)層的職責(zé)是什么?它主要負(fù)責(zé)什么?我們知道,表現(xiàn)層中的UI層是個(gè)很薄弱的層,UI層應(yīng)該只負(fù)責(zé)與用戶進(jìn)行交互,表現(xiàn)層邏輯應(yīng)該負(fù)責(zé)協(xié)調(diào)數(shù)
據(jù)流入/流出UI層,那么這里的表現(xiàn)邏輯層應(yīng)該具有什么樣的功能。我們?cè)谇懊娼榻B業(yè)務(wù)邏輯層中也提到過(guò),我們有時(shí)候?qū)I(yè)務(wù)邏輯放在表現(xiàn)層中也是可以接收的,還是
看具體的系統(tǒng)需要。
有的時(shí)候我們很鐘愛(ài)把業(yè)務(wù)邏輯層中的功能反正表現(xiàn)層邏輯中,我自己的很多項(xiàng)目中也是這樣做的,因?yàn)槲夷壳暗捻?xiàng)目中也有這樣的代碼充斥者,我們說(shuō)過(guò)這不是
萬(wàn)惡的,但是當(dāng)系統(tǒng)有一定規(guī)模時(shí),表現(xiàn)邏輯層就會(huì)變成一個(gè)無(wú)所不有,無(wú)所不包的容器,難以維護(hù)和測(cè)試。
通過(guò)上面的分析我們知道,我們還是需要根據(jù)系統(tǒng)的實(shí)際需要來(lái)決定是不是把一些業(yè)務(wù)邏輯寫(xiě)在表現(xiàn)邏輯層中,對(duì)于大型的企業(yè)級(jí)項(xiàng)目來(lái)說(shuō),我們必須考慮這些問(wèn)
題,因?yàn)楹玫脑O(shè)計(jì)可以提供測(cè)試行,維護(hù)性等,我們對(duì)表現(xiàn)邏輯層的要求也會(huì)比較高,我們期望通過(guò)SOC來(lái)實(shí)現(xiàn),我們一般是通過(guò)分層來(lái)實(shí)現(xiàn),因?yàn)榉謱觼?lái)分離功能
點(diǎn),我們通過(guò)分離關(guān)注點(diǎn)可以提供表現(xiàn)邏輯層的重構(gòu),提醒更好的設(shè)計(jì)結(jié)構(gòu)和代碼結(jié)構(gòu),提高復(fù)用性。
3、WUGWYW
大家估計(jì)出一看,還以為是什么意思呢,原諒我這里賣(mài)了個(gè)關(guān)子,意思就是說(shuō)(what–user-get-is-what-you-want)用戶得到的就是你想要的。
我們?cè)谑褂脠D形化的界面設(shè)計(jì)工具時(shí),為了能更好的提供開(kāi)發(fā)效率,現(xiàn)在很多的開(kāi)發(fā)工具提供了界面預(yù)覽的功能,基本上是所見(jiàn)即所得,但是并不是全部,例如
Visio Studio 提供的web開(kāi)發(fā)中的預(yù)覽,但是有時(shí)候我們還需要自己動(dòng)手去處理一些表現(xiàn)層的東西,所以我們會(huì)對(duì)界面通過(guò)CSS去控制UI層的顯示,我這里解釋這個(gè)的
意思就是,有時(shí)候我們需要多寫(xiě)一些代碼來(lái)提供更好的功能,滿足用戶的需求。
4.3、MVC模式的提出及演化
從本節(jié)開(kāi)始我們就開(kāi)始對(duì)表現(xiàn)層中的模式進(jìn)行講解,我們主要是針對(duì)MVC模式的起源及發(fā)展過(guò)程進(jìn)行講解。
4.2.2、MVC模式(Model-View-Controller)
MVC模式起源于上個(gè)世紀(jì)80年代,目前已經(jīng)有了30年的歷史了,在現(xiàn)在的今天,可能我們沒(méi)有辦法再使用原來(lái)的定義去完成表現(xiàn)層的設(shè)計(jì)了,但是我們現(xiàn)在使用
的MVC模式都是從原來(lái)的MVC模式中演變過(guò)來(lái)的,以適應(yīng)目前的軟件開(kāi)發(fā)需求。我們這里可能說(shuō)的MVC模式也不是原始的定義,包括后面介紹的MVP模式等。
我們這里需要知道表現(xiàn)層都有哪些分類,每種分類可能演變出哪些哪些分類等,這對(duì)我們對(duì)表現(xiàn)層的模式有個(gè)大概的結(jié)構(gòu),對(duì)我們對(duì)表現(xiàn)層的設(shè)計(jì)有很大的幫助,
下面我們來(lái)看看吧:

我們將會(huì)詳細(xì)的講解這些模式及應(yīng)用,本節(jié)將詳細(xì)的講解MVC的演變及原
理,其中由MVC模式演變的Model2模式正式目前ASP.NET MVC的實(shí)現(xiàn)方式。
在早起我們開(kāi)發(fā)表現(xiàn)層的時(shí)候,我想我們更多的是將表現(xiàn)層邏輯與視圖放在一個(gè)文件中,可以看作是功能自治的視圖。用戶與視圖交互,視圖負(fù)責(zé)捕獲用戶的輸入
信息,并在內(nèi)部處理,然后更新自己或者跳轉(zhuǎn)到另外一個(gè)視圖。這樣的組織形式,不但難以維護(hù),更難測(cè)試,因此更加讓大家渴望有一種好的模式,從這樣復(fù)雜的表現(xiàn)
層中分離出來(lái),由此MVC模式便提出來(lái)了。
MVC模式的提出,將我們從視圖自治的設(shè)計(jì)方式脫離出來(lái),自治的視圖內(nèi)部的處理,可能包含業(yè)務(wù)層,數(shù)據(jù)訪問(wèn)層或者服務(wù)層等等,當(dāng)然還有自身的設(shè)計(jì)層。MVC
模式,則讓我們把自治視圖的功能進(jìn)行分離,將自治視圖分解成,視圖層,控制層,模型的形式,來(lái)分離關(guān)注點(diǎn),通過(guò)關(guān)注點(diǎn)的分離,來(lái)降低系統(tǒng)的復(fù)雜度,進(jìn)而提供
系統(tǒng)的更好的設(shè)計(jì)性。
那么MVC模式,也有人稱作模范,那么MVC到底是模式還是模范呢?我們來(lái)看看模式與模范的定義吧?可能就更能理解MVC了
模式在軟件領(lǐng)域中是指一個(gè)被證明過(guò)的,具體的某類問(wèn)題的解決方案。
模范是指某一類相似問(wèn)題的解決方案,一般是指一類相似的模式。
通過(guò)上面的解釋,我們知道MVC是模式。
我們來(lái)看看自治視圖與MVC的結(jié)構(gòu)上的區(qū)別,MVC模式我們知道將自治視圖中的功能進(jìn)行分離,分離成功能相對(duì)獨(dú)立的組件,并且通過(guò)這些組件的交互完成表現(xiàn)層
的工作。

可以這樣說(shuō),自治視圖將所有的功能放在一個(gè)容器中,而MVC模式關(guān)注的是功能點(diǎn)的分
離,通過(guò)功能的分離開(kāi)實(shí)現(xiàn),我們通過(guò)將表現(xiàn)層劃分成3個(gè)不同角色的組件,通過(guò)這些組件之間的配合來(lái)完成自治視圖完成的工作。
MVC的原始定義是什么呢?我們來(lái)看看,通過(guò)書(shū)上的記載稱,MVC的原始定義中,將模型作為業(yè)務(wù)邏輯的入口,模型中,我們能夠看到程序的狀態(tài),我們需要將模
型中的數(shù)據(jù)顯示在視圖中并且視圖中接收用戶的動(dòng)作,然后通過(guò)模型來(lái)響應(yīng)用戶的操作行為。模型會(huì)處理控制器中發(fā)出的操作請(qǐng)求,一般來(lái)說(shuō)這些請(qǐng)求都會(huì)對(duì)模型的狀
態(tài)有一定改變。
但是目前隨著表現(xiàn)層模式的發(fā)展,現(xiàn)在MVC的定義已經(jīng)不像原始定義的那樣了,現(xiàn)在的模型只負(fù)責(zé)保持應(yīng)用程序的狀態(tài),大多數(shù)的工作都是在視圖和控制器來(lái)完
成,控制器成為更核心的組件。我們現(xiàn)有的MVC模式中對(duì)模型的定義可能更多的采用是業(yè)務(wù)中的數(shù)據(jù)對(duì)象,或者專門(mén)針對(duì)領(lǐng)域模型來(lái)構(gòu)建的領(lǐng)域?qū)ο蠡蛘呤菙?shù)據(jù)傳輸對(duì)
象。當(dāng)然還是根據(jù)我們?cè)诠ぷ髦械捻?xiàng)目的需要來(lái)決定了。我們來(lái)看看MVC模式中的簡(jiǎn)單的這幾個(gè)組件之間的調(diào)用關(guān)系吧

當(dāng)然大家請(qǐng)不要詫異,這是最原始的MVC模式的處理流程。當(dāng)今比較流行的MVC框架中流程已經(jīng)不是這樣處理的了,但是我們通過(guò)了解原始的定義將對(duì)我們更深入
的了解MVC有所幫助。MVC當(dāng)時(shí)的提出,并不是針對(duì)WEB來(lái)說(shuō)的,但是MVC模式的發(fā)展,卻是在WEB上流行起來(lái)的,像現(xiàn)在微軟提供的ASP.NET MVC框架對(duì)MVC進(jìn)
行很多的優(yōu)化和修改。我們后面會(huì)講述這個(gè)模式的原理。
我們來(lái)詳細(xì)的看看MVC中的視圖可能的代碼:一般來(lái)說(shuō)視圖層通過(guò)一些界面設(shè)計(jì)的控件元素向用戶展示相關(guān)的信息,用戶通過(guò)界面層完成與系統(tǒng)的交互,那么我們
如何在視圖中捕獲用戶的操作呢?視圖通過(guò)一些列的控件去完成用戶動(dòng)作的捕獲,比如說(shuō)輸入框,或者按鈕等,視圖的前臺(tái)通過(guò)委托與后臺(tái)的代碼綁定,我們知道,微
軟在處理.NET的表現(xiàn)層中有很大的技巧在其中,通過(guò)視圖與后臺(tái)代碼放在不同的類文件中去完成分離,這樣,視圖中用戶發(fā)出的動(dòng)作將會(huì)在代碼后置類中捕獲,然后進(jìn)
行相應(yīng)的處理。
我們先來(lái)看看控制器的可能代碼
- /// <summary>
 - /// 控制器類
 - /// </summary>
 - public class Controller
 - {
 - public void Action(ActionType actionType)
 - {
 - }
 - }
 - /// <summary>
 - /// 控制器完成的動(dòng)作
 - /// </summary>
 - public enum ActionType
 - {
 - Add,
 - Delete,
 - Query,
 - Update
 - }
 
視圖中的可能代碼:
- private void button1_Click(object sender, RoutedEventArgs e)
 - {
 - Controller controller = new Controller();
 - controller.Action(ActionType.Add);
 - }
 
代碼中的控制器可以是任何特定技術(shù)的視圖,控制器將會(huì)為視圖中每個(gè)可能發(fā)生的操作,提供一個(gè)專門(mén)的方法,每個(gè)支持用戶操作的動(dòng)作都對(duì)應(yīng)著一個(gè)與之相關(guān)的
處理服務(wù)。視圖負(fù)責(zé)數(shù)據(jù)的呈現(xiàn),控制器負(fù)責(zé)更新模型,如果模型發(fā)生變化,那么將會(huì)通過(guò)觀察者模式通知視圖其狀態(tài)發(fā)生變化,然后視圖將會(huì)決定是否將模型的變化
體現(xiàn)在視圖上,如果需要更新,那么視圖將會(huì)從模型中讀取最新的數(shù)據(jù)信息。
MVC中的模型我們上面羅列了幾種可能,如果說(shuō)我們這里的模型是業(yè)務(wù)邏輯層的話,那么我們就會(huì)直接調(diào)用業(yè)務(wù)邏輯對(duì)象中的方法完成模型狀態(tài)的更新,這些都是
控制器來(lái)完成的,如果說(shuō)MVC中的模型是數(shù)據(jù)傳輸對(duì)象,那么可能控制器將會(huì)通過(guò)業(yè)務(wù)邏輯層抽象出來(lái)的服務(wù)層的接口來(lái)訪問(wèn)與該數(shù)據(jù)傳輸對(duì)象相對(duì)應(yīng)的公開(kāi)方法去完
成模型的操作。如果說(shuō)我們這里的模型是業(yè)務(wù)模型,那么控制器只是完成路由的功能,先要解析動(dòng)作的發(fā)出者,然后要將這個(gè)動(dòng)作解析交給哪個(gè)業(yè)務(wù)模型來(lái)處理,轉(zhuǎn)發(fā)
完畢后就忘記了,其他的就有業(yè)務(wù)模型自動(dòng)完成。
控制器有時(shí)候還要負(fù)責(zé)選擇呈現(xiàn)視圖的跳轉(zhuǎn)功能,如果需要跳轉(zhuǎn)時(shí),那么控制器就會(huì)創(chuàng)建新的視圖,控制器,模型。
我們有時(shí)候可能想要通過(guò)全局配置的方式去完成重定向,比如說(shuō)通過(guò)XML文件去配置,類似工作流那樣的方式來(lái)做的話。通過(guò)配置定向頁(yè)面,那么我們?nèi)绾蝸?lái)做
呢?我們就需要提供一個(gè)服務(wù)層完成定向,比如說(shuō)通過(guò)一個(gè)通用的類去完成這樣的操作。
- <?xml version="1.0" encoding="utf-8" ?>
 - <configuration>
 - <route>
 - <urls>
 - <url key="key" value="value.aspx">
 - </url>
 - </urls>
 - </route>
 - </configuration>
 
具體的路由代碼如下:
- public class Route
 - {
 - public Route()
 - {
 - }
 - /// <summary>
 - /// 重定向服務(wù)
 - /// </summary>
 - public void RedirectUrl(string key)
 - {
 - string url = XMLHelper.GetValue(key);
 - }
 - }
 
當(dāng)然我這里只是給個(gè)可能的思路去完成服務(wù)地址的跳轉(zhuǎn),并不是比較好的方案。
通過(guò)上面的講解我們知道,視圖的更新并沒(méi)有提出由誰(shuí)來(lái)操作完成。通常來(lái)說(shuō)有2中模式,我們來(lái)看看吧

后面我們會(huì)講s解ASP.NET MVC模式中的視圖更新的模式。
我們接下來(lái)看看MVC在WEB端開(kāi)發(fā)的變體吧,那就是Model2模式,我們先來(lái)看看這種模式相比之前的MVC模式都有哪些變化吧
主要差別體現(xiàn)在以下幾個(gè)方面,在MVC模式中,視圖和模型有一定的關(guān)系,模型發(fā)生變化將會(huì)通過(guò)觀察者模式通知視圖,視圖的更新,我們是通過(guò)視圖主動(dòng)請(qǐng)
求模型來(lái)完成更新的,而在Model2中,視圖和模型是獨(dú)立的,視圖的更新是通過(guò)控制器來(lái)完成的,控制器根據(jù)模型的變化來(lái)通知視圖的呈現(xiàn)及數(shù)據(jù)的變化,還有就是該
模式中,用戶的操作不是通過(guò)視圖來(lái)捕獲的,是通過(guò)一個(gè)web組件,前端控制器來(lái)完成的,前端控制器負(fù)責(zé)攔截HTTP請(qǐng)求,然后根據(jù)這個(gè)請(qǐng)求的URL和HTTP頭信息,
去決定使用哪個(gè)控制器去處理該請(qǐng)求。

基本上這個(gè)流程是Model2的處理流程。這個(gè)流
程也是APS.NET MVC框架背后用到的模式,相信大家對(duì)背后內(nèi)容的理解,將更容易讓我們?cè)谑褂每蚣艿倪^(guò)程中加深理解。
Model2模式相比MVC模式都有什么樣的優(yōu)點(diǎn)呢?
可以肯定的是,Model2具有更好的適應(yīng)性,更好的可測(cè)試性,可維護(hù)性,并且相比原始的MVC模式,Model2的效率更高。這個(gè)怎么說(shuō)呢?
原始的MVC模式流程:我們的頁(yè)面請(qǐng)求流程是這樣的,用戶的每個(gè)操作將會(huì)產(chǎn)生一個(gè)HTTP請(qǐng)求,然后服務(wù)器根據(jù)請(qǐng)求地址,將映射一個(gè)處理頁(yè)面,然后該頁(yè)面開(kāi)
始一個(gè)生命周期,完成用戶操作的請(qǐng)求。
Model2模式的流程:通過(guò)上面的圖形我們知道,用戶的操作同樣是通過(guò)HTTP請(qǐng)求,被前端控制器捕獲,然后控制器將控制權(quán)交給具體的控制器去完成處理,而不
需要交給指定的頁(yè)面去完成處理,這樣還需要給頁(yè)面創(chuàng)建一個(gè)生命周期,同時(shí)這種方式能夠讓視圖做到非常的被動(dòng),而不是主動(dòng)更新,我們將關(guān)注點(diǎn)轉(zhuǎn)移到控制器中,
而不是視圖上,測(cè)試時(shí)更容易測(cè)試。
我們需要注意的是Model2中的模型不是業(yè)務(wù)模型,也不是領(lǐng)域模型,這個(gè)模型是專門(mén)與視圖進(jìn)行交互的對(duì)象,我們叫做ViewModel,MVC框架中會(huì)為我們提供一
個(gè)與ViewModel對(duì)應(yīng)的容器。容器負(fù)責(zé)創(chuàng)建各類的ViewModel對(duì)象。MVC的流行也是因?yàn)樗l(fā)揮了系統(tǒng)架構(gòu)的原則:分離功能點(diǎn)的重要性,所以才會(huì)讓它如此流行。
但是MVC還不完美,我們下面來(lái)看看改進(jìn)MVC不足的另外一類模式MVP。
4.3.2、MVP模式
我們閑來(lái)看看MVP模式的解釋,MVP是將MVC模式中的控制器換成展示器,MVP模式巧妙的將模型從視圖/控制器中分離開(kāi)來(lái),我們將其叫做展示器,我們需要知道MVP模式是從MVC模式的基礎(chǔ)上衍生出來(lái),在MVP模式中,我們通常是這樣去完成交互,展示器通過(guò)接口訪問(wèn)視圖,這樣做的目的是,展示器將不關(guān)心視圖的實(shí)現(xiàn)形
式,只要實(shí)現(xiàn)接口,那么就能通過(guò)展示器來(lái)完成相應(yīng)服務(wù)。當(dāng)然如果我們?cè)倏紤]展示器與模型之前的調(diào)用,如果也通過(guò)接口來(lái)完成,那么我們就將關(guān)注的中心放在展示
器上了,這樣更容易測(cè)試,視圖及模型都可以通過(guò)模擬來(lái)實(shí)現(xiàn)。這樣將大大的提高可測(cè)試性。下面我們來(lái)看看MVC模式與MVP模式的差別,我們還是通過(guò)看圖說(shuō)話的形
式,這樣更直觀。
MVP模式:

MVC模式:

通過(guò)上面的圖形,我們應(yīng)該比較清楚MVP模式相對(duì)MVC模式的改進(jìn)了吧?我這里就不多解釋了。在MVP模式中,我們更關(guān)注展示器和視圖之間的交互,我們使用該
模式的一個(gè)主要目的就是通過(guò)展示器與視圖之間通過(guò)接口調(diào)用的形式,形成低耦合的形式,我們更關(guān)注展示器,然后不同技術(shù)實(shí)現(xiàn)的視圖訪問(wèn)同一個(gè)訪問(wèn)器完成通用的
服務(wù)。這樣的方式有點(diǎn)類似SaaS的形式,軟件即是服務(wù)。
我們來(lái)看看MVP模式的工作流程:

其實(shí),MVP模式并不是一個(gè)很容易實(shí)現(xiàn)的模式,因?yàn)镸VP模式需要為每個(gè)頁(yè)面定義一個(gè)視圖接口與展示器。當(dāng)系統(tǒng)的頁(yè)面有一定的規(guī)模時(shí),這將是非常大的工作
量。因此我們需要根據(jù)項(xiàng)目的需要來(lái)決定采取的架構(gòu)模式。
我們下面來(lái)看看MVP模式衍生出來(lái)的一類新模式:Presenter Model模式,那么這個(gè)模式主要是應(yīng)用在WPF中,也會(huì)叫做Application Model ,那么這個(gè)么模式與
MVP有什么區(qū)別呢?
我們來(lái)看看,總體來(lái)說(shuō)區(qū)別不大,PM更適合WPF和silverlight中構(gòu)建表現(xiàn)層時(shí)采用的模式,與MVP模式相同,也是3個(gè)角色,視圖、展示器、模型。
在MVP模式中,我們通過(guò)為視圖定義接口,然后展示器通過(guò)接口調(diào)用的形式來(lái)和視圖進(jìn)行交互。而我們對(duì)視圖的數(shù)據(jù)綁定則是,通過(guò)視圖實(shí)現(xiàn)接口來(lái)完成的。那么
具體的實(shí)現(xiàn)技術(shù)可以有所不同。
在PM模式中,視圖不會(huì)暴露任何的接口。在該模式中通過(guò)在展示器中引入與視圖綁定的數(shù)據(jù)模型,通過(guò)這樣的方式,視圖就是被動(dòng)的,當(dāng)數(shù)據(jù)模型的狀態(tài)發(fā)生改變
時(shí),由于.NET FrameWork已經(jīng)提供了底層的數(shù)據(jù)綁定的同步,所以模型狀態(tài)發(fā)送改變時(shí),視圖將會(huì)自動(dòng)的同步更新。通過(guò)這樣的雙向綁定的方式來(lái)完成我們之前的
MVP模式完成的功能,不過(guò)交互的結(jié)構(gòu)發(fā)生變化,流程上也有一定的區(qū)別,我們來(lái)看看PM模式中3個(gè)角色的交互關(guān)系:

知道了這3個(gè)角色之間的關(guān)系,那么具體的流程是怎樣呢?還是看圖說(shuō)話,更容易理解。

視圖與模型是雙向綁定,雙方會(huì)自動(dòng)根據(jù)某一方的變化來(lái)自動(dòng)更
新,其實(shí)就是視圖會(huì)被動(dòng)的根據(jù)實(shí)體的變化來(lái)更新,展示器通過(guò)接收用戶的動(dòng)作,執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,然后更新模型,模型發(fā)生變化,由于視圖與模型綁定,那么視
圖也被動(dòng)變化。我們可以把這里模型就看做是數(shù)據(jù)傳輸對(duì)象那樣的類,只是有存儲(chǔ)數(shù)據(jù)的屬性,而沒(méi)有任何的行為的載體即可。PM模式在WPF中該模式叫做MVVM。
我們來(lái)總結(jié)下我們講過(guò)的這些模式的不同UI的應(yīng)用情形吧:

我們這里大概的總結(jié)下,不同模式的應(yīng)用場(chǎng)景,希望能夠?qū)Υ蠹移綍r(shí)項(xiàng)目中的設(shè)計(jì)有所幫助。
五、結(jié)束語(yǔ)
本文主要講述了系統(tǒng)架構(gòu)中的表現(xiàn)層中的一些比較常見(jiàn)的基類表現(xiàn)層的模式,并且針對(duì)這些的模式的底層原理進(jìn)行了簡(jiǎn)單的說(shuō)明。這里并沒(méi)有給出太多的實(shí)例代
碼,是因?yàn)楹竺娴囊恍?shí)例中都會(huì)用到這里的一些模式,像MVP,PM的模式等,如果可以的話,我后面可以單獨(dú)的開(kāi)篇舉例說(shuō)明這些模式的應(yīng)用。
作者:CallHot-何戈洲
出處:http://www.cnblogs.com/hegezhou_hot/
關(guān)于作者:專注于微軟平臺(tái)項(xiàng)目架構(gòu)、管理和企業(yè)解決方案。熟悉設(shè)計(jì)模式、極限編程、架構(gòu)設(shè)計(jì)、敏捷開(kāi)發(fā)和項(xiàng)目管理?,F(xiàn)主要從事WinForm、ASP.NET、等方面的項(xiàng)目開(kāi)發(fā)、架構(gòu)、管理工作。如有問(wèn)題或建議,請(qǐng)多多賜教!
【編輯推薦】
- 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之開(kāi)卷有益
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)建模1
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)建模2
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)建模3
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)建模4
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)設(shè)計(jì)規(guī)范與原則1
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)設(shè)計(jì)規(guī)范與原則2
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之業(yè)務(wù)邏輯層
 - 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之表現(xiàn)層
 















 
 
 
 
 
 
 