MVC、MVP和MVVM以及MVA比較

banq發表於2018-11-24

模型-檢視-控制器(MVC)模式好像是無處不在,Web框架使用它,GUI客戶端使用它,但可能這只是一個營銷謊言(如果你想仔細分辨他們的區別,如果你認真,你就可能錯了)。他們實際是在使用像MVA這樣的東西。

MVC的歷史
MVC是在70年代發明的,當時Alan Kay和他的團隊在Xerox Parc的Dynabook和Smalltalk工作, Trygve MH Reenskaug記得
我建立了模型 - 檢視 - 控制器模式,作為從多個角度看待使用者控制其資訊的一般問題的明顯解決方案。MVC創造了令人驚訝的興趣。有些文字甚至使用變態變體實現計算機控制使用者的相反目的。

MVC不是1994年Gang of Four四人幫《設計模式》一書中的一部分。我認為Smalltalk實現是MVC參考,因為它是多個專案和開發人員使用的第一個例項。
2003年,Reenskaug重新審視了他的設計,並將其分為多種模式。他稱之為MVC模式語言

  • “模型/編輯器分離”描述了模型與介面的分離以與之互動。這使得模型能夠接近使用者的心理模型,這被認為是良好的物件導向設計。模型中不需要考慮介面。
  • “輸入/輸出分離”是關於透過控制器處理使用者輸入並透過檢視將模型呈現給使用者的分割。這個基本思想歸功於Smalltalk-80實現。
  • “任務工具”模式是“原始MVC”。它解決的問題是“為使用者提供執行一項或多項任務的工具。該工具應該讓使用者產生與模型直接互動的錯覺。”

從GoF設計模式術語表達:控制器和檢視部件是模型的外觀facade模式

來自架構原則的MVC
我們還可以從架構原則中推匯出MVC,並且由於我們可以簡單地分兩步描述設計模式,這兩個步驟直接對映到Reenskaug的“模型/編輯器分離”和“輸入/輸出分離”。

  1. 在分層架構中,我們希望將UI與較低階別的模型分離。較低的水平一定不能知道更高的水平。他們使用抽象來進行更鬆散的耦合。因此,我們必須使用觀察者從模型呼叫UI。
  2. 我們還希望將使用者互動與圖形表示分離以增加內聚力,因此我們在UI層上拆分為控制器和檢視。由於它們都必須直接引用模型,因此它們保持在同一水平,並且可以自由地進行互動而無需觀察者解耦。

這種推導是我將模型的繪製必須低於控制器和檢視的原因。Smalltalk-80的描述似乎有相同的想法。
第二步在當今的環境中沒有很好的動力。通常不需要實際拆分控制器和檢視。John Gossmann 在2005年評論道
Controller在現代GUI開發中究竟發生了什麼,這是一個漫長的題外話......我傾向於認為它剛剛陷入了背景。它仍然存在,但我們不必像1979年那樣考慮它

但是,作為一個框架建立者,您如果宣告是MVC,就會給人一種熟悉的感覺。在這種情況下,只需在UI層中選擇兩個元件,即可呼叫一個檢視,再呼叫另一個檢視。

MVC的變化
Model-View-Presenter(MVP)是一個MVC變體。Greer繪製的類圖與他的MVC類圖完全相同,只是他將“Controller”改為“Presenter”。這僅暗示實際差異:Controller控制器具有處理輸入的主要工作,並可相應地修改模型。Presenter演示者具有修改模型的主要工作,而檢視也處理輸入。

Model-View-ViewModel(MVVM)還將輸入處理合併到檢視中,它完全解耦模型和檢視。在MVC中,檢視直接連線到模型,而反向是透過觀察者抽象的。MVVM將檢視與模型斷開連線,並將ViewModel作為中間體間接地引入。例如,ViewModel中常見的是選擇邏輯,它通常會同時影響多個GUI元素。
MVVM的主要動機是使檢視能夠在沒有任何邏輯的情況下由XML定義,因此沒有程式設計技能的UI設計人員可以構建它。
使用MVVM的主要場景不是Smalltalk,而是Microsofts WPF應用程式。
MVVM也是Fowlers Passive View 理念的一個例項, 其動機是改進的可測試性:GUI不能很好地進行單元測試,因此將GUI部分縮小並儘可能多地放入其他程式碼。

模型 - 檢視 - 介面卡(MVA)
MVA完全解耦模型和檢視,但不打算在檢視中沒有邏輯,輸入也來自檢視,因此這將控制器變為純粹的介面卡。當需要將資料庫架構與GUI分離時,介面卡很有價值。
由於MVA和MVVM的類圖是同構的,我認為MVVM是WPF特定的MVA。

結論
MVC不是一個定義明確的概念,所以不要認為它是上述模式中任何一個。把它當成像“雲”這樣的流行語會更好。MVC在特定的上下文中可能是精確的(例如Android應用程式開發),但通常只是一個模糊的概念。

如果您設計一個系統,那麼考慮MVC與MVVM和MVP之類的選項是沒有幫助的。相反,找出潛在的問題,並在必要時解決它們。例如,UI和模型之間的耦合可能是一個問題,因為它會使其中任何一個更改成本更高,因為您還必須調整其他部分。您可以使用觀察者而不是直接呼叫來主動解耦它們。你也可以使用觀察者以外的東西,或者根本不使用它。
 

相關文章