1. 程式人生 > >雜談: MVC/MVP/MVVM

雜談: MVC/MVP/MVVM

前言

本文為回答一位朋友關於MVC/MVP/MVVM架構方面的疑問所寫, 旨在介紹iOS下MVC/MVP/MVVM三種架構的設計思路以及各自的優缺點. 全文約五千字, 預計花費閱讀時間20 – 30分鐘.

MVC

  • MVC的相關概念
    MVC最早存在於桌面程式中的, M是指業務資料, V是指使用者介面, C則是控制器. 在具體的業務場景中, C作為M和V之間的連線, 負責獲取輸入的業務資料, 然後將處理後的資料輸出到介面上做相應展示, 另外, 在資料有所更新時, C還需要及時提交相應更新到介面展示. 在上述過程中, 因為M和V之間是完全隔離的, 所以在業務場景切換時, 通常只需要替換相應的C, 複用已有的M和V便可快速搭建新的業務場景. MVC因其複用性, 大大提高了開發效率, 現已被廣泛應用在各端開發中.

概念過完了, 下面來看看, 在具體的業務場景中MVC/MVP/MVVM都是如何表現的.

  • MVC之消失的C層
112595746-29036860ea42fbf8

上圖中的頁面(業務場景)或者類似頁面相信大家做過不少, 各個程式設計師的具體實現方式可能各不一樣, 這裡說說我所看到的部分程式設計師的寫法:

123456789101112131415161718192021222324252627282930313233343536 //UserVC-(void)viewDidLoad{[superviewDidLoad];[[UserApi new]fetchUserInfoWithUserId:132completionHandler:^(NSError *error,id result){if(error){[selfshowToastWithText:@"獲取使用者資訊失敗了~"];}else{self.userIconIV
.image=...self.userSummaryLabel.text=......}}];[[userApi new]fetchUserBlogsWithUserId:132completionHandler:^(NSError *error,id result){if(error){[selfshowErrorInView:self.tableView info:...];}else{[self.blogs addObjectsFromArray:result];[self.tableView reloadData];}}];}//...略-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{BlogCell *cell=[tableView dequeueReusableCellWithIdentifier:@"BlogCell"];cell.blog=self.blogs[indexPath.row];returncell;}-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{[self.navigationController pushViewController:[BlogDetailViewController instanceWithBlog:self.blogs[indexPath.row]]animated:YES];}//...略
12345678 //BlogCell-(void)setBlog:(Blog)blog{_blog=blog;self.authorLabel.text=blog.blogAuthor;self.likeLebel.text=[NSString stringWithFormat:@"贊 %ld",blog.blogLikeCount];...}

程式設計師很快寫完了程式碼, Command+R一跑, 沒有問題, 心滿意足的做其他事情去了. 後來有一天, 產品要求這個業務需要改動, 使用者在看他人資訊時是上圖中的頁面, 看自己的資訊時, 多一個草稿箱的展示, 像這樣:

122595746-f98abdd550485408 於是小白將程式碼改成這樣:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546 //UserVC-(void)viewDidLoad{[superviewDidLoad];if(self.userId!=LoginUserId){self.switchButton.hidden=self.draftTableView.hidden=YES;self.blogTableView.frame=...}[[UserApi new]fetchUserI......[[UserApi new]fetchUserBlogsWithUserId:132completionHandler:^(NSError *error,id result){//if Error...略[self.blogs addObjectsFromArray:result];[self.blogTableView reloadData];}];[[userApi new]fetchUserDraftsWithUserId:132completionHandler:^(NSError *error,id result){//if Error...略[self.drafts addObjectsFromArray:result];[self.draftTableView reloadData];}];}-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{returntableView==self.blogTableView?self.blogs.count:self.drafts.count;}//...略-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{if(tableView==self.blogTableView){BlogCell *cell=[tableView dequeueReusableCellWithIdentifier:@"BlogCell"];cell.blog=self.blogs[indexPath.row];returncell;}else{DraftCell *cell=[tableView dequeueReusableCellWithIdentifier:@"DraftCell"];cell.draft=self.drafts[indexPath.row];returncell;}}-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{if(tableView==self.blogTableView)...}//...略
12345678910 //DraftCell-(void)setDraft:(draft)draft{_draft=draft;self.draftEditDate=...}//BlogCell-(void)setBlog:(Blog)blog{...同上}

後來啊, 產品覺得使用者看自己的頁面再加個回收站什麼的會很好, 於是程式設計師又加上一段程式碼邏輯 , 再後來…
隨著需求的變更, UserVC變得越來越臃腫, 越來越難以維護, 拓展性和測試性也極差. 程式設計師也發現好像程式碼寫得有些問題, 但是問題具體出在哪裡? 難道這不是MVC嗎?
我們將上面的過程用一張圖來表示:

132595746-e8770c633cb5cc74
通過這張圖可以發現, 使用者資訊頁面作為業務場景Scene需要展示多種資料M(Blog/Draft/UserInfo), 所以對應的有多個View(blogTableView/draftTableView/image…), 但是, 每個MV之間並沒有一個連線層C, 本來應該分散到各個C層處理的邏輯全部被打包丟到了Scene這一個地方處理, 也就是M-C-V變成了MM…-Scene-…VV, C層就這樣莫名其妙的消失了.
另外, 作為V的兩個cell直接耦合了M(blog/draft), 這意味著這兩個V的輸入被綁死到了相應的M上, 複用無從談起.
最後, 針對這個業務場景的測試異常麻煩, 因為業務初始化和銷燬被繫結到了VC的生命週期上, 而相應的邏輯也關聯到了和View的點選事件, 測試只能Command+R, 點點點…
  • 正確的MVC使用姿勢

也許是UIViewController的類名給新人帶來了迷惑, 讓人誤以為VC就一定是MVC中的C層, 又或許是Button, Label之類的View太過簡單完全不需要一個C層來配合, 總之, 我工作以來經歷的專案中見過太多這樣的”MVC”. 那麼, 什麼才是正確的MVC使用姿勢呢?
仍以上面的業務場景舉例, 正確的MVC應該是這個樣子的:

142595746-2d7ea66f64955f87

UserVC作為業務場景, 需要展示三種資料, 對應的就有三個MVC, 這三個MVC負責各自模組的資料獲取, 資料處理和資料展示, 而UserVC需要做的就是配置好這三個MVC, 並在合適的時機通知各自的C層進行資料獲取, 各個C層拿到資料後進行相應處理, 處理完成後渲染到各自的View上, UserVC最後將已經渲染好的各個View進行佈局即可, 具體到程式碼中如下:

12345678 @interfaceBlogTableViewHelper:NSObject+(instancetype)helperWithTableView:(UITableView *)tableView userId:(NSUInteger)userId;-(void)fetchDataWithCompletionHandler:(NetworkTaskCompletionHander)completionHander;-(void)setVCGenerator:(ViewControllerGenerator)VCGenerator;@end
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 @interfaceBlogTableViewHelper()@property(weak,nonatomic)UITableView *tableView;@property(copy,nonatomic)ViewControllerGenerator VCGenerator;@property(assign,nonatomic)NSUInteger userId;

相關推薦

雜談: MVC/MVP/MVVM

前言 本文為回答一位朋友關於MVC/MVP/MVVM架構方面的疑問所寫, 旨在介紹iOS下MVC/MVP/MVVM三種架構的設計思路以及各自的優缺點. 全文約五千字, 預計花費閱讀時間20 – 30分鐘. MVC MVC的相關概念 MVC最早存在於桌面程式中的, M是指業務資

Android App的設計架構:MVC,MVP,MVVM與架構經驗談

用戶 自己的 req html pla 觀察 持久化 重構 his 來源: Android App的設計架構:MVC,MVP,MVVM與架構經驗談 和MVC框架模式一樣,Model模型處理數據代碼不變在Android的App開發中,很多人經常會頭疼於App的架構如何設計:

淺析前端開發中的 MVC/MVP/MVVM 模式

所有 團隊 sub 策略 代碼 告訴 簡單 ava 關心 MVC,MVP和MVVM都是常見的軟件架構設計模式(Architectural Pattern),它通過分離關註點來改進代碼的組織方式。不同於設計模式(Design Pattern),只是為了解決一類問題而總結出的抽

MVC,MVP,MVVM

route src HA 路由 路由器 控制器 view 數據保存 9.png MVC MVC模式的意思是,軟件可以分成三個部分 視圖(View):用戶界面。 控制器(Controller):業務邏輯 模型(Model):數據保存 實際項目往往采用更靈活的方式,以 Back

MVC/MVP/MVVM

現在 也有 lis 驗證 設定 思考 不同 最大的 也好 架構模式的文章很多,好理解的沒有幾個。大部分文章出現的主要問題有: 沒有設定好作用域:前端MVC是改造過的MVC,和後臺MVC有明顯的區別,不能一概而論 沒有實際的例子:實際的例子對應日常的工作,沒有就很難產

MVC-MVP-MVVM框架模式分析

無法 連接 不能 相互 轉化 觀察者 作用 展示 .com MVC(Model-View-Controller) MVC 架構模式圖(經典版) 註:實際上,Model和View永遠不能相互通信,只能通過Controller傳遞;上圖只是MVC模式的經典圖。 MVC一般流程

MVC MVP MVVM初級版

學習Vue.js的時候,官網提到了MVVM順便總結一下。慢慢熟悉。 因為是初級版,還沒有時間做出太詳細的總結,先在這裡Mark一下,把網路上能搜尋到的概念和資源先拷貝過來。後續再看情況寫中級版和高階版。 MVC MVC是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(

談談MVC-MVP-MVVM的漸進使用和誤解

講這三種設計模式之前,咱先列舉一個使用場景,現在有如下需求: 開發需求:頁面有個列表用於顯示新聞,新聞可以收藏,點贊 首先說說MVC : L:負責承載新聞資料模型物件:標題,內容,等等 五:負責新聞展示的觀 C:負責新聞資料的業務邏輯和展示邏輯 不需要多說稍微有點經驗的人都知道

前端開發中,MVC/MVP/MVVM 的區別

MVC/MVP/MVVM 都是常見的軟體架構設計模式。說到區別,主要在於 C(Controller)、P(Presenter)、VM(View-Model)。相同點則是 MV(Model-View)。 Model Model 層用於封裝和應用程式的業務邏輯相關的資料以及對

你真的理解了MVC, MVP, MVVM嗎?

點選上方“程式設計師小灰”,選擇“置頂公眾號”有趣有內涵的文章第一時間送達!本文轉載自公眾號 

android 架構模式MVC,MVP,MVVM

  從只會實現功能的“碼農”到軟體工程師、設計師的過渡。   MVP/MVVM架構的優點和缺點?它的使用場景是什麼?   MVC是一種框架模式而非設計模式,GOF把MVC看作是3種設計模式:觀察者模式、策略模式與組合模式的合體,而核心是觀察者模式。簡而言之,框架是大智慧,用

iOS架構模式-揭祕MVC,MVP,MVVM和VIPER

iOS架構模式揭祕MVC,MVP,MVVM和VIPER英文原文:https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52#.w3sovqjl3作者:Bohdan Orlov翻譯

android MVC && MVP && MVVM分析和對比

  面試的時候被問到這個問題,用過,也瞭解過,但是還是不夠深入,總結一下。   MVC,MVP和MVVM是軟體比較常用的三種軟體架構,這三種架構的目的都是分離關注,避免將過多的邏輯全部堆積在一個類中,以android為例,在activity中既有UI的相關處理

MVC, MVP, MVVM比較以及區別

MVC, MVP和MVVM都是用來解決介面呈現和邏輯程式碼分離而出現的模式。以前只是對它們有部分的瞭解,沒有深入的研究過,對於一些裡面的概念和區別也是一知半解。現在一邊查資料,並結合自己的理解,來談一下對於這三種模式思想的理解,以及它們的區別。 一,MVC, MVP

MVC, MVP, MVVM比較以及區別(下)

 上一篇得到大家的關注,非常感謝。一些朋友評論中,希望快點出下一篇。由於自己對於這些模式的理解也是有限,所以這一篇來得遲了一些。對於這些模式的比較,是結合自己的理解,一些地方不一定準確,但是隻有亮出自己的觀點,才能拋磚引玉不是? 歡迎各位拍磚。:) 閱讀目錄: 四. MVP模式      4

MVC, MVP, MVVM比較以及區別(上)

MVC, MVP和MVVM都是用來解決介面呈現和邏輯程式碼分離而出現的模式。以前只是對它們有部分的瞭解,沒有深入的研究過,對於一些裡面的概念和區別也是一知半解。現在一邊查資料,並結合自己的理解,來談一下對於這三種模式思想的理解,以及它們的區別。歡迎各位高手拍磚。 閱讀目錄: 一. MVC, M

iOS架構模式MVC+MVP+mvvm架構

隨著iOS職位的火熱,越來越多的人都想成為一名優秀的iOS開發工程師,那麼在競爭激烈的時代,應該如何成為一名iOS開發工程師呢?現在讓大家瞭解一下iOS架構模式作為一個開發者,有一個學習的氛圍跟一個交流圈子特別重要這是一個我的iOS交流群:687528266,不管你是小白還是

Android 系統(77)---MVC,MVP,MVVM的區別

MVC,MVP,MVVM的區別一、MVC 軟體可以分為三部分1.Model:模型層,負責處理資料的載入或者儲存 2. View:檢視層,負責介面資料的展示,與使用者進行互動 3.Controller:控制器層,負責邏輯業務的處理各部分之間的通訊方式如下:View傳送指令到Co

揭開MVC,MVP,MVVM,VIPER這幾種模式的神祕面紗

iOS Architecture Patterns Demystifying MVC, MVP, MVVM and VIPER Feeling weird while doing MVC in iOS? Have doubts about switchi

MVC/MVP/MVVM 前端框架模式

簡單來講就是:檢視(View):使用者介面控制器(Controller):業務邏輯模型(Model):資料儲存使用者操作介面,View接受指令,View 傳送指令到 Controller,也就是從View層到Control層的箭頭所示Controller 完成業務邏輯後,要求 Model 改變狀態,也就是從C