本頁使用了標題或全文手工轉換

MVC

維基百科,自由的百科全書
跳到: 導覽搜尋

MVC模式(Model–view–controller)是軟件工程中的一種軟件架構模式,把軟件系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。

MVC模式最早由Trygve Reenskaug在1978年提出[1],是施樂帕羅奧多研究中心(Xerox PARC)在20世紀80年代為程式語言Smalltalk發明的一種軟件架構。MVC模式的目的是實現一種動態的程式設計,使後續對程式的修改和擴充功能簡化,並且使程式某一部分的重複利用成為可能。除此之外,此模式通過對複雜度的簡化,使程式結構更加直覺。軟件系統通過對自身基本部分分離的同時也賦予了各個基本部分應有的功能。專業人員可以通過自身的專長分組:

  • 控制器(Controller)- 負責轉發請求,對請求進行處理。
  • 視圖(View) - 介面設計人員進行圖形介面設計。
  • 模型(Model) - 程式設計師編寫程式應有的功能(實現演算法等等)、數據庫專家進行數據管理和數據庫設計(可以實現具體的功能)。
MVC模式

元件的互動[編輯]

MVC元件之間的典型合作

將應用程式劃分為三種元件,模型 - 視圖 - 控制器(MVC)設計定義它們之間的相互作用。[2]

  • 模型(Model) 用於封裝與應用程式的業務邏輯相關的數據以及對數據的處理方法。「 Model 」有對數據直接存取的權力,例如對數據庫的存取。「Model」不依賴「View」和「Controller」,也就是說, Model 不關心它會被如何顯示或是如何被操作。但是 Model 中數據的變化一般會通過一種重新整理機制被公佈。為了實現這種機制,那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在數據 Model 上發生的改變。(比較:觀察者模式軟件設計模式))
  • 視圖(View)能夠實現數據有目的的顯示(理論上,這不是必需的)。在 View 中一般沒有程式上的邏輯。為了實現 View 上的重新整理功能,View 需要存取它監視的數據模型(Model),因此應該事先在被它監視的數據那裏註冊。
  • 控制器(Controller)起到不同層面間的組織作用,用於控制應用程式的流程。它處理事件並作出響應。「事件」包括用戶的行為和數據 Model 上的改變。

優點[編輯]

在最初的JSP網頁中,像數據庫查詢陳述式(SQL query)這樣的數據層代碼和像HTML這樣的表示層代碼是混在一起。雖然有着經驗比較豐富的開發者會將數據從表示層分離開來,但這樣的良好設計通常並不是很容易做到的,實現它需要精心地計劃和不斷的嘗試。MVC可以從根本上強制性地將它們分開。儘管構造MVC應用程式需要一些額外的工作,但是它帶給我們的好處是毋庸置疑的。

首先,多個 View 能共享一個 Model 。如今,同一個Web應用程式會提供多種使用者介面,例如用戶希望既能夠通過瀏覽器來收發電子郵件,還希望通過手機來存取電子郵箱,這就要求Web網站同時能提供Internet介面和WAP介面。在MVC設計模式中, Model 響應用戶請求並返迴響應數據,View 負責格式化數據並把它們呈現給用戶,業務邏輯和表示層分離,同一個 Model 可以被不同的 View 重用,所以大大提高了代碼的可重用性。

其次,Controller 是自包含(self-contained)指高獨立內聚的物件,與 Model 和 View 保持相對獨立,所以可以方便的改變應用程式的數據層和業務規則。例如,把數據庫從MySQL移植到Oracle,或者把RDBMS資料來源改變成LDAP資料來源,只需改變 Model 即可。一旦正確地實現了控制器,不管數據來自數據庫還是LDAP伺服器,View 都會正確地顯示它們。由於MVC模式的三個模組相互獨立,改變其中一個不會影響其他兩個,所以依據這種設計思想能構造良好的少互擾性的構件。

此外,Controller 提高了應用程式的靈活性和可配置性。Controller 可以用來連線不同的 Model 和 View 去完成用戶的需求,也可以構造應用程式提供強有力的手段。給定一些可重用的 Model 、 View 和Controller 可以根據用戶的需求選擇適當的 Model 進行處理,然後選擇適當的的 View 將處理結果顯示給用戶。

評價及適用範圍[編輯]

MVC模式在概念上強調 Model, View, Controller 的分離,各個模組也遵循着由 Controller 來處理訊息,Model 掌管資料來源,View 負責數據顯示的職責分離原則,因此在實作上,MVC 模式的 Framework 通常會將 MVC 三個部份分離實作:

  • Model 負責數據存取,較現代的 Framework 都會建議使用獨立的數據物件 (DTO, POCO, POJO 等) 來替代弱型別的集合物件。數據存取的程式碼會使用 Data Access 的程式碼或是 ORM-based Framework,也可以進一步使用 Repository Pattern 與 Unit of Works Pattern 來切割資料來源的相依性。
  • Controller 負責處理訊息,較高階的 Framework 會有一個預設的實作來作為 Controller 的基礎,例如 Spring 的 DispatcherServlet 或是 ASP.NET MVC 的 Controller 等,在職責分離原則的基礎上,每個 Controller 負責的部份不同,因此會將各個 Controller 切割成不同的檔案以利維護。
  • View 負責顯示數據,這個部份多為前端應用,而 Controller 會有一個機制將處理的結果 (可能是 Model, 集合或是狀態等) 交給 View,然後由 View 來決定怎麼顯示。例如 Spring Framework 使用 JSP 或相應技術,ASP.NET MVC 則使用 Razor 處理數據的顯示。

也因為 MVC 模式強調職責分離,所以在發展 MVC 應用時會產生很多檔案,在 IDE (整合開發環境) 不夠成熟時它會是個問題,但在現代主流 IDE 都能使用類別物件的資訊來組織程式碼編輯的情況下,多檔案早已不是問題,而且 MVC 模式會要求開發者進一步思考應用程式的架構 (Application Architecture),而非用大雜燴的方式開發應用程式,對於應用程式的生命週期以及後續的可擴充與可維護性而言有相當正面的幫助。另外,MVC 職責分離也帶來了一個現代軟件工程要求的重要特性:可測試性 (Testability),MVC-based 的應用程式在良好的職責分離的設計下,各個部份可獨立行使單元測試,有利於與企業內的自動化測試、持續整合 (Continuous Integration) 與持續發行 (Continuous Delivery) 流程整合,減少應用程式改版部署所需的時間。

MVC 模式的應用程式的目的就是希望打破以往應用程式使用的大雜燴程式撰寫方式,並間接誘使開發人員以更高的架構導向思維來思考應用程式的設計,因此對於一個剛入門的初學者來說,架構導向的思考會有一定的門檻,需要較多的實作與練習才能具備相應的能力,大多數的初學者還是較習慣於大雜燴式的程式撰寫,所以可能會對 MVC 模式抱持着排斥或厭惡的心態,然而 MVC (或是其他的Design Patterns) 都是有助於應用程式長遠的發展,雖然大雜燴式的程式也可以用來發展長生命週期的應用程式,但是相較於 MVC,大雜燴式的程式在可擴充性和可維護性 (尤其是可測試性) 上會遠比 MVC 複雜很多,相反的,MVC 模式的應用程式是在初始開發時期必須先思考並使用軟件架構,使得開發時期會需要花較多心力,但是一旦應用程式完成後,可擴充性、可維護性和可測試性反而會因為 MVC 的特性而變得容易。

因此,MVC 模式在已有眾多優秀 Framework 的現代,早就已經沒有不適合小型應用的問題,小型的應用還是可以由 MVC Framework 的應用來獲取 MVC 的優點,同時它也能作為未來小型應用擴充到大型應用時的基礎與入門磚。若一開始就想要做大型應用,那麼 MVC 模式的職責分離以及要求開發的架構思考會更適合大型應用的開發。

實際範例[編輯]

這裏有一個透過 JavaScript 所實現的一個基礎 MVC 模型,請注意的是:MVC 不是一種技術,僅是一種理念。

/** 模擬 Model, View, Controller */
var M = {}, V = {}, C = {};

/** Model 負責存放資料 */
M.data = "hello world";

/** View 負責將資料輸出到螢幕上 */
V.render = (M) => { alert(M.data); }

/** Controller 作為一個 M 和 V 的橋樑 */
C.handleOnload = () => { V.render(M); }

/** 在網頁讀取的時候呼叫 Controller */
window.onload = C.handleOnload;

在這個簡短的程式碼中就具有一個完整的 MVC 模式。

實現[編輯]

MFC[編輯]

微軟所推出的MFC Document/View架構是早期對於MVC模式的實現,MFC將程式分成CView以及CDocument兩大類別,其中的Document對應MVC中的 Model ,View 相當於MVC中的 View+Controller,再加上CWinApp類別,合成三大項。但是基本上MFC是一個失敗的MVC模式作品。

由於MFC之下的Document/View 定義過於模糊,未將Controller(MessageMap)部份取出,因此 Controller 可以置入 View 或Document,但不管置入哪一方面,都會與View或Document綁死,沒有彈性。

Java[編輯]

Java 平台企業版 (J2EE)[編輯]

和其他的各種框架不一樣,J2EE為模型物件(Model Objects)定義了一個規範。

視圖(View)
在J2EE應用程式中,視圖(View)可能由Java Server Page(JSP)擔任。生成 View 的代碼則可能是一個servlet的一部分,特別是在用戶端伺服端互動的時候。
控制器(Controller)
J2EE應用中,Controller 可能是一個servlet
除了可直接以J2EE來撰寫外,亦可用其他框架來撰寫,常見的有Struts2Spring Framework……等等。
模型(Model)
Model 則是由一個實體Bean來實現。

Java Swing[編輯]

Swing是一個標準的MVC結構. ComponentUI代表 View, 負責描畫元件. 元件尤其 Model 層, 比如JTextField的Document, JTable的TableModel, JTree的TreeModel等等. 而Control可能不是很明顯, 我們或許可以簡單的將其Event機制看作一個Swing團隊開發給開發者的 Controller。

作為Java開發者, 如果想理解MVC的結構, 學習Swing的確是個不錯的選擇.

.NET[編輯]

ASP.NET[編輯]

在ASP.NET中,針對視圖(View)和控制器(Controller)的模式沒有被很好地定義。而模型(Model)則留給開發者去設計。

視圖(View)
ASPX和ASCX檔案被用來處理 View 的職責。在這個設計中 View 實際上是從 Controller 繼承而來。這個和Smalltalk的實施有所不同,在Smalltalk中不同的類都有指標互相指向對方.
控制器(Controllers)
Controller 的職責被分割成兩部分。事件(Event)的產生和傳輸是框架的一部分,更明確的說是Page和Control兩個類。而事件的處理則在分離的代碼中實現。
模型(Model)
ASP.NET 不嚴格需要一個 Model。開發者可以自行選擇建立一個 Model 類,但是很多人選擇放棄這一步,直接把事件處理放在 Controller 里處理任何計算、數據儲存等等。但用 Model 來包含商業邏輯和數據存取是可實現的。

ASP.NET MVC[編輯]

此外,在ASP.NET MVC中,一般情況下Model通常搭配LINQ to SQL類別(使用O/R Designer工具所製作而成的DBML檔)或ADO.NET實體數據模型(Entity Data Model,使用ADO.NET Entity Framework製作出的EDMX檔)來實作。

Windows Forms[編輯]

在WinForms中,這個針對視圖(View)和控制器(Controller)的模式已經很好的定義。而模型(Model)則留給開發者去設計。

視圖(View)
由Form或者Control類繼承來的一個類處理 View 的職責。在WinForm這個例子中 View 和 Controller 被編譯在同一個類中,這個和ASP.NET不同。
控制器(Controller)
Controller 的職責被分割成三部分。事件(Event)的產生和傳輸是作業系統的一部分。在.Net框架中Form和Control類將不同的事件轉發給相應的事件處理器。而事件的處理則在分離的代碼中實現。
模型(Model)
就像ASP.NET一樣,WinForm不嚴格需要一個 Model。開發者可以自行選擇建立一個 Model 類,但是很多人選擇放棄這一步,直接把事件處理放在 Controller 里處理任何計算、數據儲存等等。也就是說用Model來包含商業邏輯和數據存取。

Perl[編輯]

CatalystJifty是透過Perl語言所開發出來的Web Framework,都採用Model-View-Controller 架構。Catalyst 本身只是做了 Controller,View 和 Model 讓開發者自由選用 CPAN 上的模組開發,例如 Template 和 Template Declare 都可用來產生視圖。Jifty 將 MVC 完全實做完成,View 的部份在早期版本使用 Mason 實做,較新版本使用 Template Declare。

Ruby on Rails[編輯]

Ruby on Rails是透過Ruby語言所開發出來的 Web Framework,也是採用 Model-View-Controller 架構。Model 部份使用 Active Record 概念實做,加上 Migration 機制,使得其 Model 結構非常容易控制。

Python[編輯]

Python 有許多的 MVC 架構。最常用的有 DjangoTurboGears

JavaScript[編輯]

PHP[編輯]

ActionScript 3[編輯]

參考文獻[編輯]

  1. ^ Reenskaug, Trygve. THING-MODEL-VIEW-EDITOR: an Example from a planningsystem (PDF). 
  2. ^ Buschmann, Frank (1996) Pattern-Oriented Software Architecture.
  3. ^ ASP.NET MVC 概觀

外部連結[編輯]