理解並運用MVC,MVP,MVVM

来源:https://www.cnblogs.com/chaihuibin/p/18185614
-Advertisement-
Play Games

前言 MVC,MVP,MVVM 屬於 GUI 軟體設計,它們都強調將軟體的視圖顯示與業務邏輯進行分離,將軟體拆分為三個部分,分別負責數據操作、視圖邏輯、業務邏輯。 業務邏輯指的是任何與數據操作、視圖操作的定義與實現無關的功能。 具體來說,業務邏輯中不應該出現如何操作視圖或如何操作數據的細節。 對於這 ...


前言

MVC,MVP,MVVM 屬於 GUI 軟體設計,它們都強調將軟體的視圖顯示與業務邏輯進行分離,將軟體拆分為三個部分,分別負責數據操作、視圖邏輯、業務邏輯。

業務邏輯指的是任何與數據操作、視圖操作的定義與實現無關的功能。
具體來說,業務邏輯中不應該出現如何操作視圖或如何操作數據的細節。
對於這些操作,應該在視圖層或數據層定義相關的功能,在這些功能內實現相關操作,再由業務邏輯去調用這些功能的 API。

這三個部分對程式有一個簡單的劃分:

  • Model 負責維護軟體的數據,實現那些處理數據的功能,供外部調用,它保持獨立,不依賴 View 與 Controller。
  • View 負責用戶界面,將數據展示用戶,實現那些操作視圖的功能,供外部調用。
  • Conttoller/Presenter/ViewModel:
    負責實現軟體的業務邏輯,協調 View 與 Model,將 Model 的數據展示到 View 的用戶界面,並將 View 對數據的更改更新至 Model。

MVC

MVC 將軟體按功能進行拆分,但是對各部分的職責、各部分的協作關係沒有很明確的約束。

根據職責與關係的不同,MVC 也有不同的實現。

Passive View MVC

被動視圖指得是 View 的用戶界面被動的等待更新,它不依賴 Model 來操作數據,將 View 數據的初始化、更新以及對 Model 數據的更新交給 Controller。

這樣的定義使得 Model 與 View 都是獨立的,可被覆用。

那 Model, View, Controller 具體該承擔什麼樣的職責呢?

  • Model 的職責很明確,提供操作數據的功能。

  • Passive View 呢?是不是意味著著它只能定義如何操作視圖,但不能自行操作呢?
    不然,對於那些隻影響視圖,不涉及 Model 數據操作的視圖操作,應該由 View 自行處理,沒有必要再委托 Controller 來調用。而那些與 Model 數據相關的視圖操作,可以由 View 封裝好供 Controller調用。比如獲取數據要訪問網路,屬於耗時操作,過程中要展示進度條,那針對進度條的操作就應該封裝為 API 以供外部調用

  • Controller 負責具體的業務邏輯。對於 View 中響應用戶輸入的功能,凡是涉及業務邏輯的,View 自己不實現,而是在 Controller 中實現,View 去調用。

View 可以持續響應用戶的輸入,如果將所有的業務邏輯都放在 Controller 中,會使得 Controller 任務繁重。
雖然可以通過將 Controller 拆分為多個子模塊來解決這個問題,但是思考如何為各個子模塊分配職責也是個麻煩事兒。另外, 對 Model 與 View 調用可能會分散在代碼的許多地方,難以管理。

要解決 Controller 任務重的問題,可以將部分業務邏輯轉移出去,比如 Model 與 View 之間的數據同步邏輯是可以放在 View 中。

要實現數據的同步,View 需要知道 Model 的數據變化,而 Model 因為不能依賴 View,也就不能去更新 View。要解決這個問題,可以使用觀察者模式。

Observer Pattern

引入觀察者模式,將 Model 定義為可觀察對象,這樣 View 就可以在 Model 數據更新後更新用戶界面了。除了 View, Controller 也能向 Model 註冊觀察者,執行一些與用戶界面無關的操作。

Active Model MVC / Active View MVC

View 可以主動的更新視圖,Model 也可以將自身變化主動的通知觀察者,應用觀察者模式的 MVC 可以被稱作 Active View MVC 或 Active Model MVC。

View 與 Model 之間的數據同步操作,可能是簡單的,比如將數據原封不動地傳遞,或者進行數據拼接、類型轉換;
也可能是複雜的,比如類似加解密這樣的複雜計算,訪問網路處理數據,調用第三方軟行處理數據,之後再進行同步操作。

不可能將所有的數據同步邏輯都轉移到 View 中,好的做法是將簡單的同步操作放在 View 中實現,複雜的在 Controller 中實現。

WEB MVC

在伺服器端 WEB 軟體開發也有 MVC 的概念,但是 View 往往只是一個 HTML 文檔, 不能響應用戶輸入,但瀏覽器根據 HTML 來渲染界面,倒是也符合 MVC 對 View 的定義。

MVP

MVP 就是 MVC,MVP 有兩種實現定義:

  1. Passive View MVP: 就是 Passive View MVC
  2. Supervising Controller MVP: 就是 Active View MVC,是將簡單的同步操作放在 View 中實現,複雜的在 Prennter 中實現

真要說有什麼不同,可能就是 MVP 強制約定了 View 與 Model 的關係,而 MVC 對此並無限制。

在 OOP 項目實踐中,View 被定義為介面,而 Presenter 被定義為類,View 被註入到 Presenter 中,這樣可以保證 View 與 Presenter 能被一起複用。

MVC / MVP 代碼示例

Android Java 偽代碼:

interface IView {
  public void showPeogressbar();
  public void cancelPeogressbar();
}
class Presenter {
  private Iview view;
  void Presenter(IView v){
    this.view = v;
  }
  
  public void logic() {
    this.view.showPeogressbar();
    // dosth
    this.view.cancelPeogressbar();
  }
}

class MainActivity implements IView() {
  private Presenter presenter;
  public void onCreate() {
    this.presenter = new Presenter(this);
    findViewById(R.id.btn).setOnclickListente((View view)->{
      this.presenter.logic();
    });
  }
  
  public void showPeogressbar() {}
  public void cancelPeogressbar() {}
}

MVVM

MVC 和 MVP 本質上是一樣的,而 Model-View-ViewModel(MVVM) 也是將軟體分為三個部分,ViewModel 與 MVC 的 Controller 職責也是一樣的,負責業務邏輯。MVP 並沒有給MVC引入什麼新的概念,但 MVVM 引入了新的概念:

  • 將視圖從業務邏輯中分離
  • 視圖狀態
  • 數據驅動視圖

視圖的狀態

  • 視圖中會變化的數據
  • 視圖用於響應用戶輸入的業務邏輯,即視圖的行為

視圖的狀態的本質是給視圖引入了一個代理,即 ViewModel,通過代理來間接操作視圖。

分離視圖與業務邏輯

將視圖從業務邏輯中分離的核心是業務邏輯中不操作視圖,只操作數據,在業務邏輯中不會去訪問視圖的細節。分離視圖的方式是實現 數據驅動視圖

數據驅動視圖

數據驅動視圖的直觀表現是,改變數據,視圖就更新。其原理是 ViewModel 維護一個數據集合,與 View 的狀態一一對應。本質上還是觀察者模式,View 通過觀察 ViewModel 的數據變化,來更新視圖。而 View 因用戶輸入產生的狀態變化也會主動更新到 ViewModel 的數據集合中。

需要註意的是,ViewModel 名字里的 'Model' 指得是 View 的狀態所對應的數據,而與 Model 無關,View 狀態的更新不會同步到 Model 中。
更改 ViewModel 的數據以更新 View 狀態,屬於視圖邏輯,而同步 View 狀態對應的數據到 Model中是業務邏輯,我們還要自行實現。

聲明式 UI

視圖的數據和行為的綁定操作不會憑空就能從業務邏輯中分離,我們肯定要寫代碼來實現,但是也不可能每個 View 都先編寫一個 ViewModel,那樣會有太多的樣板代碼。

既然寫代碼麻煩,那就生成代碼。使用特定的文本格式,或者說標記語言來聲明視圖,在聲明中為視圖綁定 ViewModel,為控制項綁定狀態(數據和行為),然後寫一個解析器來生成代碼。

不同的開發平臺有不同的實現,比如 Javascript Web 應用使用 HTML 或者 JSX 聲明視圖,Android 使用 XML 或 Compose 來說明視圖,而微軟的 WPF .NET 使用 xaml, Blazor 使用 razor。

使用標記語言來定義視圖,真正做到了將視圖的關註點從業務邏輯中分離,因為解析器只用編寫一次,算不得業務邏輯。

一切皆數據

數據驅動視圖的開發方式已經是所有追求先進性的 GUI 軟體開發框架所必備的了。

在 ViewModel 中是沒有 View 的細節的,只有 View 的狀態所對應的數據。開發業務邏輯的過程中可以完全當視圖不存在,一切都是數據。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在 JavaScript 中,實現深拷貝的方式有很多種,每種方式都有其優點和缺點。今天介紹一種原生 JavaScript 提供的structuredClone實現深拷貝。 下麵列舉一些常見的方式,以及它們的代碼示例和優缺點: 1. 使用 JSON.parse(JSON.stringify(obj)) ...
  • XML Schema描述了 XML 文檔的結構。XML Schema語言也稱為 XML Schema Definition(XSD)。 <?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs: ...
  • 1、通過${}來獲取model中的變數,註意這不是el表達式,而是ognl表達式,但是語法非常像 <h2 th:object="${user}"> <p>Name: <span th:text="*{name}">Jack</span>.</p> <p>Age: <span th:text="*{a ...
  • Qwerty Learner —— 一款為鍵盤工作者設計的單詞記憶與英語肌肉記憶鍛煉軟體,主要服務於以英語作為主要工作語言的鍵盤工作者。 ...
  • ​ UIOTOS可以瞭解下,uiotos.net,通過連線來代替腳本邏輯開發,複雜的交互界面,通過頁面嵌套輕鬆解決,是個很新穎的思路,前端零代碼! 藍圖連線尤其是獨創的頁面嵌套和屬性繼承技術,好家伙相當於把vue的組件化、增量式面向對象開發,直接搬到前端拖拽工具上,無代碼編程了。 總的來說,這上面的 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、背景 在前端JSON.stringfy是我們常用的一個方法,可以將一個對象序列化。 例如將如下對象序列化 const person = { name: 'kalory', age:18} JSON.stringfy(person) / ...
  • 引言 有這麼一個需求:列表頁進入詳情頁後,切換回列表頁,需要對列表頁進行緩存,如果從首頁進入列表頁,就要重新載入列表頁。 對於這個需求,我的第一個想法就是使用keep-alive來緩存列表頁,列表和詳情頁切換時,列表頁會被緩存;從首頁進入列表頁時,就重置列表頁數據並重新獲取新數據來達到列表頁重新載入 ...
  • 在當今的信息時代,無線通信技術的發展日新月異,為我們的工作和生活帶來了極大的便利。其中,無線通信模塊通過TCP/IP協議向PC端傳送數據已經成為了一種常見的通信方式。本文將詳細介紹這一過程的主要步驟和涉及的關鍵技術,並以WIFI模塊為例,探討如何在QT平臺下實現數據的無線傳輸。 一、無線通信模塊與T ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...