系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之表現(xiàn)層
一、前言
最近也許是由于假期的原因,我發(fā)布的文章的速度變慢了,對大家說下抱歉,這個系列的確我很難寫,感謝大家對我的支持和關(guān)注,的確我在發(fā)布后得到大家的支
持和認(rèn)可,讓我有了更多的動力,之前發(fā)布的有些內(nèi)容,可能對各層講解的內(nèi)容的廣度還不夠,當(dāng)然這和我個人的水平面有關(guān),還請各位多多提出寶貴意見和建議。
從本篇開始,我將會采用更加規(guī)范的格式,更嚴(yán)謹(jǐn)?shù)那笾獞B(tài)度,更加準(zhǔn)確的表達(dá),去將接下來的系列文章寫完,并且與群中的很多朋友交流后,他們希望出一個總
的PDF電子書,這樣可以方便閱讀,的確謝謝各位的支持,我目前將以后每篇寫的內(nèi)容,放一份PDF格式的在群共享中,有需要的朋友可以進(jìn)行相應(yīng)的下載,由于本人
的寫作水平有限,所以在書寫的深度和書寫的格式上還有很多的缺點,還希望大家多多指出。
二、開篇
本篇我們將針對系統(tǒng)架構(gòu)分層中的表現(xiàn)層進(jìn)行講述,分析表現(xiàn)層的架構(gòu)與設(shè)計模式,當(dāng)然我們會結(jié)合目前比較流行的表現(xiàn)層模式進(jìn)行分析講解,主要是圍繞MVC模
式的起源及發(fā)展的過程進(jìn)行講述,并且分析目前MVC模式在不同UI層中的應(yīng)用設(shè)計,由于本人的水平有限,加之實際的項目中可能應(yīng)用的理解和經(jīng)驗水平不足,可能在
某些分析的地方不對,還請大家提出。我們之前的寫作慣例,我們先來看看本文的主要講述的內(nèi)容吧
本文將會以上面的2點為主線展開去講解表現(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模式的對比和總結(jié)
5、結(jié)束語
6、系列進(jìn)度
7、下篇預(yù)告
四、表現(xiàn)層模式
4.1、表現(xiàn)層的職責(zé)
我們知道任何一個應(yīng)用程序,如果想要更好的與客戶交互,我們一般都是通過提供一個用戶界面去完成與用戶的交互,當(dāng)然通過前面我們講述的,服務(wù)層與業(yè)務(wù)邏
輯層的講解,其實都是為了更好的為表現(xiàn)層服務(wù)的,通常,我們都不是特別的重視表現(xiàn)層,但是其實,表現(xiàn)層同樣重要。其實通常我們在關(guān)注各個分層的時候,我們對
每個分層的重視程度會不同,可能是由于我們自身的愛好,態(tài)度,或者是專業(yè)技能所決定的,但是一個好的系統(tǒng),必然要求我們不管哪個分層都要足夠的重視。
我們在做表現(xiàn)層時,通常我們會關(guān)注下面幾個組件,首先是用戶界面。也就是客戶能夠看到的用戶界面簡稱UI,還有一部分就是與用戶行為進(jìn)行交互的組件,通常
我們叫做表現(xiàn)層邏輯,用戶的所有操作都通過表現(xiàn)層邏輯來支持,表現(xiàn)邏輯層將負(fù)責(zé)其他層與UI層之間的交互。
根據(jù)我們前面講述的各分層的設(shè)計我們知道,表現(xiàn)層邏輯將主要與服務(wù)層或者業(yè)務(wù)邏輯層進(jìn)行交互。具體的關(guān)系如下:
通過上圖我們知道表現(xiàn)邏輯層的位置,可以說如何組織好用戶界面及表現(xiàn)層邏輯同其他層之間的關(guān)系,就是決定設(shè)計好壞的關(guān)鍵。也可以說表現(xiàn)層邏輯決定了用戶
與系統(tǒng)交互。
下面我們來先看看表現(xiàn)層的職責(zé)吧
我們一般都把如下職責(zé)看作是表現(xiàn)層的職責(zé),是不是你也有相同的看法?
其實,像圖中說的驗證,格式化,添加樣式等這些更應(yīng)該屬于UI層組件,而不應(yīng)該屬于表現(xiàn)層,但
是作為架構(gòu)師,你必須考慮的更全面,從更高的層次去考慮,比如說下面的幾個方面:
只有更好的考慮這些因素,才能決定表現(xiàn)層的架構(gòu),我們針對上面的幾個方面來
簡單的分析一下。
1、UI的無關(guān)性:
這里的UI的無關(guān)性就是指不依賴UI層的實現(xiàn)技術(shù),不管是上面說的Web還是Winform,還是其他的WPF、WP還是其他的任何UI表現(xiàn)形式。我們知道這樣的表現(xiàn)
層設(shè)計出來是理想的,我們只是想盡可能的提高可復(fù)用性,我們希望的是雖然不同的UI使用的實現(xiàn)技術(shù)不同,但是這些UI能夠共用表現(xiàn)層邏輯,這時候我們就能做到很
好的復(fù)用性。
我們需要知道,這里提出的代碼重用只是說是盡可能大的做到表現(xiàn)層邏輯重用,但是有些情況我們沒有辦法做到,例如Silverlight與WPF,由于他們使用不同的
CLR,所以我們只能說是做到代碼重用,我們需要針對他們各自進(jìn)行單獨的編譯。
2、可測試性
任何分層都需要能夠測試,因為只有測試才能知道功能是否能夠很好的滿足需求。但是通常來說表現(xiàn)層的測試,相比其他分層要復(fù)雜一些,因為表現(xiàn)層需要考慮的
因素很多,所以決定了測試的難度,所以更好的測試性就是我們架構(gòu)設(shè)計的基本要求。
一般來說我們在表現(xiàn)層的處理流程是這樣的:
上面的圖中大概描述了,我們在表現(xiàn)層中的基本流程,我們來結(jié)合圖形來說明下:用戶界面通過用戶
操作,將觸發(fā)相應(yīng)的行為事件,這些事件將會被某個特殊的控制器進(jìn)行處理,控制器通過發(fā)送給指定的處理函數(shù),然后將處理函數(shù)返回的結(jié)果,反饋給用戶界面。
通過上面的流程我們知道,我們測試時必須模擬用戶的行為,并且如何保證用戶的行為事件能夠得到正確的處理,這些都是我們必須測試的內(nèi)容。我們?nèi)绻麑⑺?/p>
的內(nèi)容都寫在表現(xiàn)層,那么我想可能測試起來不會那么容易,如果說我們的用戶界面與表現(xiàn)層邏輯寫在一個頁面中,可能我們并不容易測試,幸好APS.NET中通過代碼
后置的技術(shù),實現(xiàn)設(shè)計層與表現(xiàn)層邏輯代碼的分離。當(dāng)然我們在之前就對架構(gòu)設(shè)計的實現(xiàn)提出了一個觀點,就是分離功能點,將關(guān)注的功能點進(jìn)行分離,提出更高的抽
象,這樣可以達(dá)到更好的測試的目的。
3、不依賴數(shù)據(jù)模型
在服務(wù)層、業(yè)務(wù)邏輯層中我們都提到了數(shù)據(jù)傳輸對象,并且把這個對象作為與表現(xiàn)層通信的載體,使用了數(shù)據(jù)傳輸對象后,那么我們就可以做到表現(xiàn)層不依賴于我
們的數(shù)據(jù)模型,但是我們也講過,數(shù)據(jù)傳輸對象為項目帶來了更多的類,更多的工程文件,所以這會對我們的開發(fā)工作帶來額外的工作量。因為不同的表現(xiàn)層需要一個
與之對應(yīng)的數(shù)據(jù)傳輸對象,這些都和前面我們介紹的情況是一致的。因此,我們在項目中是否使用數(shù)據(jù)傳輸對象,我們需要根據(jù)項目的需要來決定。
4、不依賴圖形化元素
我們這里的圖形化元素是指,開發(fā)工具給我們提供的控件和工具集合,我們通過這些圖形化元素設(shè)計出與用戶交互的界面,我們希望我們的表現(xiàn)層能夠在不同的控
件上可以以不同的方式表現(xiàn)出來,我們同時希望圖形化元素中的任意修改不會影響到表現(xiàn)層邏輯,舉個例子,我們平時在博客園中的模板設(shè)計,其實就是個很好的例
子,我們選擇不同的模板,我們的博客頁面就會在皮膚,樣式,主題等方面都發(fā)生變化,但是并不影響我們的表現(xiàn)層。
4.2、UI層與表現(xiàn)層邏輯
4.2.1、用戶界面的職責(zé)
我們接下來看看UI層的相關(guān)職責(zé),我們知道,我們平時在系統(tǒng)設(shè)計過程中,一般架構(gòu)師不會直接參與到用戶的界面的設(shè)計中,架構(gòu)師更側(cè)重系統(tǒng)的可用性和可訪問
性。我們認(rèn)為UI層的主要功能包括下面幾項:
下面我們來分別說說吧
1、數(shù)據(jù)顯示
我們都知道UI層是用戶使用系統(tǒng)的唯一入口,那么首先用戶界面必須將系統(tǒng)中的一些信息進(jìn)行展示,這些信息可能包括,普通信息、提示信息、系統(tǒng)中的相關(guān)數(shù)據(jù)
信息等,良好的設(shè)計UI能夠很好的展示數(shù)據(jù),用戶界面需要支持本地化及全球化功能。
2、友好的交互
交互就體現(xiàn)在用戶使用系統(tǒng)的功能,這樣就會有這樣的操作,用戶輸入相應(yīng)的數(shù)據(jù),通常來說一個好的UI層,會提供給用戶一個比較人性化的輸入頁面,并且會根
據(jù)用戶的輸入,返回用戶想得到的結(jié)果。不管UI層的具體技術(shù)是什么,好的用戶交互頁面都是系統(tǒng)中最重要的部分。輸入的數(shù)據(jù)我們?nèi)绾巫龅桨踩苑矫娴尿炞C,是我
們必須重視的部分。
3、總體外觀
系統(tǒng)的功能都是通過用戶界面來作為統(tǒng)一入口,提供給用戶使用的,所以一般來說我們在設(shè)計UI時必須要有精致的用戶界面,軟件的目的就是抓住用戶,能夠給用
戶較好的用戶體驗,而且根據(jù)軟件的用戶群來進(jìn)行不同的設(shè)計,如果是提供給大眾使用的軟件,那么我們必須達(dá)到設(shè)計精致的用戶界面的要求,如果是提供給企業(yè)內(nèi)部
使用,那么我們可以注重功能而不是視覺效果的震撼,當(dāng)然不是說不重視UI,只是沒有那么重視。
4.2.2、表現(xiàn)層中容易產(chǎn)生的誤區(qū)
我們來看看我們平時在表現(xiàn)層的設(shè)計與實現(xiàn)過程中可能存在的誤區(qū)吧
我們來看看每個誤區(qū)的說明吧
1、過度依賴工具
自從有了Visual Studio 開發(fā)工具以來,就因為其提供了大量的控件,為我們開發(fā)簡單的應(yīng)用程序提供了很大的方便,我們通常都是通過拖拽控件來完成UI層的設(shè)
計。我們通過一些帶有事件的控件,去完成與其他層之間的交互,我們可以在事件中直接處理邏輯,而且很方便很快捷。這也使得我們的開發(fā)效率很高,當(dāng)然這是開發(fā)
簡單的應(yīng)用程序時我們通過這樣來做,沒有什么問題。但是,當(dāng)我們開發(fā)大型的企業(yè)級應(yīng)用時,這樣的方式可能就不是理想的選擇了,為什么這么說呢?我們不是說不
用開發(fā)工具提供的控件,而是應(yīng)該將職責(zé)進(jìn)行劃分,比如說,用設(shè)計器完成界面的設(shè)計,然后其他的代碼都是通過我們的手工邊寫,而不是通過開發(fā)工具提供的一些控
件去完成,比如說Visio Studio 提供的數(shù)據(jù)源綁定控件等,而且如何將事件中的代碼進(jìn)行更好的抽象就是我們這里的需要考慮的問題。
2、表現(xiàn)層的邊界
我們先要清楚表現(xiàn)層的職責(zé)是什么?它主要負(fù)責(zé)什么?我們知道,表現(xiàn)層中的UI層是個很薄弱的層,UI層應(yīng)該只負(fù)責(zé)與用戶進(jìn)行交互,表現(xiàn)層邏輯應(yīng)該負(fù)責(zé)協(xié)調(diào)數(shù)
據(jù)流入/流出UI層,那么這里的表現(xiàn)邏輯層應(yīng)該具有什么樣的功能。我們在前面介紹業(yè)務(wù)邏輯層中也提到過,我們有時候?qū)I(yè)務(wù)邏輯放在表現(xiàn)層中也是可以接收的,還是
看具體的系統(tǒng)需要。
有的時候我們很鐘愛把業(yè)務(wù)邏輯層中的功能反正表現(xiàn)層邏輯中,我自己的很多項目中也是這樣做的,因為我目前的項目中也有這樣的代碼充斥者,我們說過這不是
萬惡的,但是當(dāng)系統(tǒng)有一定規(guī)模時,表現(xiàn)邏輯層就會變成一個無所不有,無所不包的容器,難以維護(hù)和測試。
通過上面的分析我們知道,我們還是需要根據(jù)系統(tǒng)的實際需要來決定是不是把一些業(yè)務(wù)邏輯寫在表現(xiàn)邏輯層中,對于大型的企業(yè)級項目來說,我們必須考慮這些問
題,因為好的設(shè)計可以提供測試行,維護(hù)性等,我們對表現(xiàn)邏輯層的要求也會比較高,我們期望通過SOC來實現(xiàn),我們一般是通過分層來實現(xiàn),因為分層來分離功能
點,我們通過分離關(guān)注點可以提供表現(xiàn)邏輯層的重構(gòu),提醒更好的設(shè)計結(jié)構(gòu)和代碼結(jié)構(gòu),提高復(fù)用性。
3、WUGWYW
大家估計出一看,還以為是什么意思呢,原諒我這里賣了個關(guān)子,意思就是說(what–user-get-is-what-you-want)用戶得到的就是你想要的。
我們在使用圖形化的界面設(shè)計工具時,為了能更好的提供開發(fā)效率,現(xiàn)在很多的開發(fā)工具提供了界面預(yù)覽的功能,基本上是所見即所得,但是并不是全部,例如
Visio Studio 提供的web開發(fā)中的預(yù)覽,但是有時候我們還需要自己動手去處理一些表現(xiàn)層的東西,所以我們會對界面通過CSS去控制UI層的顯示,我這里解釋這個的
意思就是,有時候我們需要多寫一些代碼來提供更好的功能,滿足用戶的需求。
4.3、MVC模式的提出及演化
從本節(jié)開始我們就開始對表現(xiàn)層中的模式進(jìn)行講解,我們主要是針對MVC模式的起源及發(fā)展過程進(jìn)行講解。
4.2.2、MVC模式(Model-View-Controller)
MVC模式起源于上個世紀(jì)80年代,目前已經(jīng)有了30年的歷史了,在現(xiàn)在的今天,可能我們沒有辦法再使用原來的定義去完成表現(xiàn)層的設(shè)計了,但是我們現(xiàn)在使用
的MVC模式都是從原來的MVC模式中演變過來的,以適應(yīng)目前的軟件開發(fā)需求。我們這里可能說的MVC模式也不是原始的定義,包括后面介紹的MVP模式等。
我們這里需要知道表現(xiàn)層都有哪些分類,每種分類可能演變出哪些哪些分類等,這對我們對表現(xiàn)層的模式有個大概的結(jié)構(gòu),對我們對表現(xiàn)層的設(shè)計有很大的幫助,
下面我們來看看吧:
我們將會詳細(xì)的講解這些模式及應(yīng)用,本節(jié)將詳細(xì)的講解MVC的演變及原
理,其中由MVC模式演變的Model2模式正式目前ASP.NET MVC的實現(xiàn)方式。
在早起我們開發(fā)表現(xiàn)層的時候,我想我們更多的是將表現(xiàn)層邏輯與視圖放在一個文件中,可以看作是功能自治的視圖。用戶與視圖交互,視圖負(fù)責(zé)捕獲用戶的輸入
信息,并在內(nèi)部處理,然后更新自己或者跳轉(zhuǎn)到另外一個視圖。這樣的組織形式,不但難以維護(hù),更難測試,因此更加讓大家渴望有一種好的模式,從這樣復(fù)雜的表現(xiàn)
層中分離出來,由此MVC模式便提出來了。
MVC模式的提出,將我們從視圖自治的設(shè)計方式脫離出來,自治的視圖內(nèi)部的處理,可能包含業(yè)務(wù)層,數(shù)據(jù)訪問層或者服務(wù)層等等,當(dāng)然還有自身的設(shè)計層。MVC
模式,則讓我們把自治視圖的功能進(jìn)行分離,將自治視圖分解成,視圖層,控制層,模型的形式,來分離關(guān)注點,通過關(guān)注點的分離,來降低系統(tǒng)的復(fù)雜度,進(jìn)而提供
系統(tǒng)的更好的設(shè)計性。
那么MVC模式,也有人稱作模范,那么MVC到底是模式還是模范呢?我們來看看模式與模范的定義吧?可能就更能理解MVC了
模式在軟件領(lǐng)域中是指一個被證明過的,具體的某類問題的解決方案。
模范是指某一類相似問題的解決方案,一般是指一類相似的模式。
通過上面的解釋,我們知道MVC是模式。
我們來看看自治視圖與MVC的結(jié)構(gòu)上的區(qū)別,MVC模式我們知道將自治視圖中的功能進(jìn)行分離,分離成功能相對獨立的組件,并且通過這些組件的交互完成表現(xiàn)層
的工作。
可以這樣說,自治視圖將所有的功能放在一個容器中,而MVC模式關(guān)注的是功能點的分
離,通過功能的分離開實現(xiàn),我們通過將表現(xiàn)層劃分成3個不同角色的組件,通過這些組件之間的配合來完成自治視圖完成的工作。
MVC的原始定義是什么呢?我們來看看,通過書上的記載稱,MVC的原始定義中,將模型作為業(yè)務(wù)邏輯的入口,模型中,我們能夠看到程序的狀態(tài),我們需要將模
型中的數(shù)據(jù)顯示在視圖中并且視圖中接收用戶的動作,然后通過模型來響應(yīng)用戶的操作行為。模型會處理控制器中發(fā)出的操作請求,一般來說這些請求都會對模型的狀
態(tài)有一定改變。
但是目前隨著表現(xiàn)層模式的發(fā)展,現(xiàn)在MVC的定義已經(jīng)不像原始定義的那樣了,現(xiàn)在的模型只負(fù)責(zé)保持應(yīng)用程序的狀態(tài),大多數(shù)的工作都是在視圖和控制器來完
成,控制器成為更核心的組件。我們現(xiàn)有的MVC模式中對模型的定義可能更多的采用是業(yè)務(wù)中的數(shù)據(jù)對象,或者專門針對領(lǐng)域模型來構(gòu)建的領(lǐng)域?qū)ο蠡蛘呤菙?shù)據(jù)傳輸對
象。當(dāng)然還是根據(jù)我們在工作中的項目的需要來決定了。我們來看看MVC模式中的簡單的這幾個組件之間的調(diào)用關(guān)系吧
當(dāng)然大家請不要詫異,這是最原始的MVC模式的處理流程。當(dāng)今比較流行的MVC框架中流程已經(jīng)不是這樣處理的了,但是我們通過了解原始的定義將對我們更深入
的了解MVC有所幫助。MVC當(dāng)時的提出,并不是針對WEB來說的,但是MVC模式的發(fā)展,卻是在WEB上流行起來的,像現(xiàn)在微軟提供的ASP.NET MVC框架對MVC進(jìn)
行很多的優(yōu)化和修改。我們后面會講述這個模式的原理。
我們來詳細(xì)的看看MVC中的視圖可能的代碼:一般來說視圖層通過一些界面設(shè)計的控件元素向用戶展示相關(guān)的信息,用戶通過界面層完成與系統(tǒng)的交互,那么我們
如何在視圖中捕獲用戶的操作呢?視圖通過一些列的控件去完成用戶動作的捕獲,比如說輸入框,或者按鈕等,視圖的前臺通過委托與后臺的代碼綁定,我們知道,微
軟在處理.NET的表現(xiàn)層中有很大的技巧在其中,通過視圖與后臺代碼放在不同的類文件中去完成分離,這樣,視圖中用戶發(fā)出的動作將會在代碼后置類中捕獲,然后進(jìn)
行相應(yīng)的處理。
我們先來看看控制器的可能代碼
- /// <summary>
- /// 控制器類
- /// </summary>
- public class Controller
- {
- public void Action(ActionType actionType)
- {
- }
- }
- /// <summary>
- /// 控制器完成的動作
- /// </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ù)的視圖,控制器將會為視圖中每個可能發(fā)生的操作,提供一個專門的方法,每個支持用戶操作的動作都對應(yīng)著一個與之相關(guān)的
處理服務(wù)。視圖負(fù)責(zé)數(shù)據(jù)的呈現(xiàn),控制器負(fù)責(zé)更新模型,如果模型發(fā)生變化,那么將會通過觀察者模式通知視圖其狀態(tài)發(fā)生變化,然后視圖將會決定是否將模型的變化
體現(xiàn)在視圖上,如果需要更新,那么視圖將會從模型中讀取最新的數(shù)據(jù)信息。
MVC中的模型我們上面羅列了幾種可能,如果說我們這里的模型是業(yè)務(wù)邏輯層的話,那么我們就會直接調(diào)用業(yè)務(wù)邏輯對象中的方法完成模型狀態(tài)的更新,這些都是
控制器來完成的,如果說MVC中的模型是數(shù)據(jù)傳輸對象,那么可能控制器將會通過業(yè)務(wù)邏輯層抽象出來的服務(wù)層的接口來訪問與該數(shù)據(jù)傳輸對象相對應(yīng)的公開方法去完
成模型的操作。如果說我們這里的模型是業(yè)務(wù)模型,那么控制器只是完成路由的功能,先要解析動作的發(fā)出者,然后要將這個動作解析交給哪個業(yè)務(wù)模型來處理,轉(zhuǎn)發(fā)
完畢后就忘記了,其他的就有業(yè)務(wù)模型自動完成。
控制器有時候還要負(fù)責(zé)選擇呈現(xiàn)視圖的跳轉(zhuǎn)功能,如果需要跳轉(zhuǎn)時,那么控制器就會創(chuàng)建新的視圖,控制器,模型。
我們有時候可能想要通過全局配置的方式去完成重定向,比如說通過XML文件去配置,類似工作流那樣的方式來做的話。通過配置定向頁面,那么我們?nèi)绾蝸碜?/p>
呢?我們就需要提供一個服務(wù)層完成定向,比如說通過一個通用的類去完成這樣的操作。
- <?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)然我這里只是給個可能的思路去完成服務(wù)地址的跳轉(zhuǎn),并不是比較好的方案。
通過上面的講解我們知道,視圖的更新并沒有提出由誰來操作完成。通常來說有2中模式,我們來看看吧
后面我們會講s解ASP.NET MVC模式中的視圖更新的模式。
我們接下來看看MVC在WEB端開發(fā)的變體吧,那就是Model2模式,我們先來看看這種模式相比之前的MVC模式都有哪些變化吧
主要差別體現(xiàn)在以下幾個方面,在MVC模式中,視圖和模型有一定的關(guān)系,模型發(fā)生變化將會通過觀察者模式通知視圖,視圖的更新,我們是通過視圖主動請
求模型來完成更新的,而在Model2中,視圖和模型是獨立的,視圖的更新是通過控制器來完成的,控制器根據(jù)模型的變化來通知視圖的呈現(xiàn)及數(shù)據(jù)的變化,還有就是該
模式中,用戶的操作不是通過視圖來捕獲的,是通過一個web組件,前端控制器來完成的,前端控制器負(fù)責(zé)攔截HTTP請求,然后根據(jù)這個請求的URL和HTTP頭信息,
去決定使用哪個控制器去處理該請求。
基本上這個流程是Model2的處理流程。這個流
程也是APS.NET MVC框架背后用到的模式,相信大家對背后內(nèi)容的理解,將更容易讓我們在使用框架的過程中加深理解。
Model2模式相比MVC模式都有什么樣的優(yōu)點呢?
可以肯定的是,Model2具有更好的適應(yīng)性,更好的可測試性,可維護(hù)性,并且相比原始的MVC模式,Model2的效率更高。這個怎么說呢?
原始的MVC模式流程:我們的頁面請求流程是這樣的,用戶的每個操作將會產(chǎn)生一個HTTP請求,然后服務(wù)器根據(jù)請求地址,將映射一個處理頁面,然后該頁面開
始一個生命周期,完成用戶操作的請求。
Model2模式的流程:通過上面的圖形我們知道,用戶的操作同樣是通過HTTP請求,被前端控制器捕獲,然后控制器將控制權(quán)交給具體的控制器去完成處理,而不
需要交給指定的頁面去完成處理,這樣還需要給頁面創(chuàng)建一個生命周期,同時這種方式能夠讓視圖做到非常的被動,而不是主動更新,我們將關(guān)注點轉(zhuǎn)移到控制器中,
而不是視圖上,測試時更容易測試。
我們需要注意的是Model2中的模型不是業(yè)務(wù)模型,也不是領(lǐng)域模型,這個模型是專門與視圖進(jìn)行交互的對象,我們叫做ViewModel,MVC框架中會為我們提供一
個與ViewModel對應(yīng)的容器。容器負(fù)責(zé)創(chuàng)建各類的ViewModel對象。MVC的流行也是因為它發(fā)揮了系統(tǒng)架構(gòu)的原則:分離功能點的重要性,所以才會讓它如此流行。
但是MVC還不完美,我們下面來看看改進(jìn)MVC不足的另外一類模式MVP。
4.3.2、MVP模式
我們閑來看看MVP模式的解釋,MVP是將MVC模式中的控制器換成展示器,MVP模式巧妙的將模型從視圖/控制器中分離開來,我們將其叫做展示器,我們需要知道MVP模式是從MVC模式的基礎(chǔ)上衍生出來,在MVP模式中,我們通常是這樣去完成交互,展示器通過接口訪問視圖,這樣做的目的是,展示器將不關(guān)心視圖的實現(xiàn)形
式,只要實現(xiàn)接口,那么就能通過展示器來完成相應(yīng)服務(wù)。當(dāng)然如果我們再考慮展示器與模型之前的調(diào)用,如果也通過接口來完成,那么我們就將關(guān)注的中心放在展示
器上了,這樣更容易測試,視圖及模型都可以通過模擬來實現(xiàn)。這樣將大大的提高可測試性。下面我們來看看MVC模式與MVP模式的差別,我們還是通過看圖說話的形
式,這樣更直觀。
MVP模式:
MVC模式:
通過上面的圖形,我們應(yīng)該比較清楚MVP模式相對MVC模式的改進(jìn)了吧?我這里就不多解釋了。在MVP模式中,我們更關(guān)注展示器和視圖之間的交互,我們使用該
模式的一個主要目的就是通過展示器與視圖之間通過接口調(diào)用的形式,形成低耦合的形式,我們更關(guān)注展示器,然后不同技術(shù)實現(xiàn)的視圖訪問同一個訪問器完成通用的
服務(wù)。這樣的方式有點類似SaaS的形式,軟件即是服務(wù)。
我們來看看MVP模式的工作流程:
其實,MVP模式并不是一個很容易實現(xiàn)的模式,因為MVP模式需要為每個頁面定義一個視圖接口與展示器。當(dāng)系統(tǒng)的頁面有一定的規(guī)模時,這將是非常大的工作
量。因此我們需要根據(jù)項目的需要來決定采取的架構(gòu)模式。
我們下面來看看MVP模式衍生出來的一類新模式:Presenter Model模式,那么這個模式主要是應(yīng)用在WPF中,也會叫做Application Model ,那么這個么模式與
MVP有什么區(qū)別呢?
我們來看看,總體來說區(qū)別不大,PM更適合WPF和silverlight中構(gòu)建表現(xiàn)層時采用的模式,與MVP模式相同,也是3個角色,視圖、展示器、模型。
在MVP模式中,我們通過為視圖定義接口,然后展示器通過接口調(diào)用的形式來和視圖進(jìn)行交互。而我們對視圖的數(shù)據(jù)綁定則是,通過視圖實現(xiàn)接口來完成的。那么
具體的實現(xiàn)技術(shù)可以有所不同。
在PM模式中,視圖不會暴露任何的接口。在該模式中通過在展示器中引入與視圖綁定的數(shù)據(jù)模型,通過這樣的方式,視圖就是被動的,當(dāng)數(shù)據(jù)模型的狀態(tài)發(fā)生改變
時,由于.NET FrameWork已經(jīng)提供了底層的數(shù)據(jù)綁定的同步,所以模型狀態(tài)發(fā)送改變時,視圖將會自動的同步更新。通過這樣的雙向綁定的方式來完成我們之前的
MVP模式完成的功能,不過交互的結(jié)構(gòu)發(fā)生變化,流程上也有一定的區(qū)別,我們來看看PM模式中3個角色的交互關(guān)系:
知道了這3個角色之間的關(guān)系,那么具體的流程是怎樣呢?還是看圖說話,更容易理解。
視圖與模型是雙向綁定,雙方會自動根據(jù)某一方的變化來自動更
新,其實就是視圖會被動的根據(jù)實體的變化來更新,展示器通過接收用戶的動作,執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,然后更新模型,模型發(fā)生變化,由于視圖與模型綁定,那么視
圖也被動變化。我們可以把這里模型就看做是數(shù)據(jù)傳輸對象那樣的類,只是有存儲數(shù)據(jù)的屬性,而沒有任何的行為的載體即可。PM模式在WPF中該模式叫做MVVM。
我們來總結(jié)下我們講過的這些模式的不同UI的應(yīng)用情形吧:
我們這里大概的總結(jié)下,不同模式的應(yīng)用場景,希望能夠?qū)Υ蠹移綍r項目中的設(shè)計有所幫助。
五、結(jié)束語
本文主要講述了系統(tǒng)架構(gòu)中的表現(xiàn)層中的一些比較常見的基類表現(xiàn)層的模式,并且針對這些的模式的底層原理進(jìn)行了簡單的說明。這里并沒有給出太多的實例代
碼,是因為后面的一些實例中都會用到這里的一些模式,像MVP,PM的模式等,如果可以的話,我后面可以單獨的開篇舉例說明這些模式的應(yīng)用。
作者:CallHot-何戈洲
出處:http://www.cnblogs.com/hegezhou_hot/
關(guān)于作者:專注于微軟平臺項目架構(gòu)、管理和企業(yè)解決方案。熟悉設(shè)計模式、極限編程、架構(gòu)設(shè)計、敏捷開發(fā)和項目管理。現(xiàn)主要從事WinForm、ASP.NET、等方面的項目開發(fā)、架構(gòu)、管理工作。如有問題或建議,請多多賜教!
【編輯推薦】
- 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之開卷有益
- 系統(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è)計規(guī)范與原則1
- 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之系統(tǒng)設(shè)計規(guī)范與原則2
- 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之業(yè)務(wù)邏輯層
- 系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之表現(xiàn)層