使用Micrisoft.net設計方案 第三章Web表示模式 Web模式集羣詳細介紹 PageController(頁面控制器)

PageController(頁面控制器)

上下文

決定使用MVC來動態創建應用程序時,需要關注把用戶界面、控制器和業務邏輯分開。

問題:

如何創建比較複雜的應用程序的控制器?

影響因數:

MVC主要關注業務模型與視圖的分開,不太關注控制器。對於胖客戶而言,控制器與視圖分開的需求不是很明顯。但在瘦客戶端,控制器與視圖本身就是分開的。由於視圖是在客戶端的瀏覽上顯示,而控制器是在服務器端執行。

由於不同用戶的操作,會產生多個操作,共用一個視圖。如果控制器和視圖不分離,視圖代碼會重複出現。例如產品查詢系統,產品查詢、分頁會使用同一個視圖,但執行不同的操作。

Web系統中不同的控制器和視圖在加載時會經理身份驗證、授權、字符串查詢等一系列操作,這些操作會使代碼重複。

腳本服務其端頁面容易創建,但顯示邏輯和業務邏輯混在一塊,隨着複雜程度的增加,難於維護、擴展和重用。

從測試角度看,測試視圖比較困難,但測試業務邏輯比較容易且重用度高,因此如果把視圖與業務邏輯、控制器分開,將容易進行測試。

解決方案

使用PageController接收用戶輸入,並根據輸入調用業務邏輯的操作,並返回結果,最後確定使用哪個視圖。這一模式使業務邏輯與視圖邏輯 進行分離(如下圖)。通常的做法是,把公用的業務邏輯寫成一個基類,PageController繼承這個基類,做到易於測試和一致性。

頁面控制器接收用戶的輸入並提取輸入的數據,同時調用模型操作,把模型操作的結果在視圖上呈現。視圖根據模型檢索的數據進行顯示。頁面控制器把模型 與視圖進行分離,頁面控制器承擔了Http請求的任務,如會話管理、緩存、認證等任務。因此我們可以爲每個鏈接創建一個控制器,每個控制器執行一個操作, 這將變的簡單。

爲每個頁面創建一個控制器,將導致大量代碼的重複,因此需要把這些公共的操作封裝到一個基類控制器中,每個頁面控制器都繼承該基類,也可以使用一些幫助類。

如果頁面相似度越高,越複雜,繼承度越深。如產品查詢系統有些需要顯示產品列表有些需要輸入數據,我們會製作兩個基類一個是 ListController和DataEntryController,頁面控制繼承他們。這樣隨着系統的複雜度增高,變的不容易維護,因此開發人員人 爲PageController是不好的設計,而FrontController是好的設計,其實這是由於對PageController缺乏完善的支 持。

大多數框架都支持PageController,如ASP、JSP、PHP等。這些框架大多數把控制器和View在服務器進行了混合,很難把進行分離。而ASP.NET對該模式進行了分離,把控制器放到一個獨立類中,使用了代碼隱藏技術。

變體

大多數情況下,頁面控制器依賴於Http請求,如請求域、請求頭部、表單域、字符串查詢等信息,因此可以把與Http請求有關的操作封裝到一個類中,把與Http有關的邏輯和與Http無關的邏輯進行了分離,見下圖:

這樣做的缺點是,增加系統開銷,好處是,容易維護和開發,尤其是多人開發的團隊尤爲重要。

PageController的優點:

1、  簡單,每個鏈接或請求,對應一個控制器,容易創建和維護,理解起來也容易。

2、  內置框架,所有框架都默認實現了該模式。

3、  容易擴展,可以使用一些幫助類進行擴展。

4、  職責分離

5、  重用度高

PageController的缺點:

1、每個頁面一個控制器。由於簡單,只能在導航比較簡單的Web系統中使用該模式,如果系統比較複雜建議使用Front Controller.

2、繼承深度比較大:由於該模式採用繼承的方式實現重用,如果業務比較複雜,繼承深度比較大,不易維護。

3、依賴Web框架

在 ASP.NET 中實現 Page Controller

在Asp.NET中構建Web應用程序,利用內置的PageController框架,同時利用ASP.NET的事件驅動特性

實現策略

在默認情況下Asp.net頁面框架實現了PageController的各種概念。Asp.NET 頁面框架自動實現了,在客戶端感知用戶操作,把用戶請求發送到服務器端,服務器端自動調用合適的方法進行響應。這個過程對開發人員來說是不可知的。頁面框 架可以進行擴展,頁面框架的各種事件都是對外開放的。

頁面生命週期

  • 下面按發生順序列出了頁面生命週期中最常見的各個階段。其中還包括引發的特定事件,以及處理請求時在各個階段可能執行的一些典型操作:

  • ASP.NET 頁面框架初始化(事件: Init )。這是生命週期的第一個步驟,該步驟將初始化 ASP.NET 運行庫以便爲響應請求做好準備。

  • 用戶代碼初始化(事件: Load )。您應該執行與應用程序具體相關的常見任務,例如,當頁面控制器引發 Load 事件時打開數據庫連接。您可以假設:引發 Load 事件後,服務器控件已創建並完成初始化、狀態已還原並且窗體控件反映了客戶端的更改。 [Reilly02]

  • 與應用程序相關的事件處理。在此階段,您應該執行與應用程序相關的處理,以響應控制器引發的事件。 .

  • 清理(事件: Unload )。 該頁面已完成生成,現在可以丟棄。您應該關閉 Load 事件打開的任何數據庫連接,丟棄任何不再需要的對象。在連接對象被作爲垃圾回收後,Microsoft.NET Framework 將自動關閉數據庫連接。不過,您對何時進行垃圾回收沒有任何控制權。因此,顯式關閉數據庫連接以充分利用數據庫連接池是一個很好的做法。

注意:還有幾個頁面處理階段沒有在這裏列出。不過,這些階段不用於大多數頁面處理情況。

實現方式


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章