如何理解Web應用程序的MVC模型?
我也編寫過一些Web應用程序,但是始終不能很好地理解MVC模型。
假設現在有一個JSP應用程序。這個應用程序實現的功能很簡單,在初始頁面上有一個輸入框和一個按鈕。用戶輸入關鍵字後,可以點擊按鈕查詢。然後這個JSP應用程序會去查詢資料庫,並把查詢結果顯示在一個結果頁面上。我也不用什麼框架,就用servlet。我如上面所說,編寫兩個JSP頁面:初始頁面和結果頁面(實際上初始頁面是個靜態頁面),以及一個servlet。我可以再搞得複雜一些,讓這個servlet再去調用一個業務邏輯對象,然後這個業務邏輯對象再去調用一個數據訪問對象,去和資料庫交互。取得查詢結果後,servlet會把查詢結果放到session里,然後forward到結果頁面。最後結果頁面用內嵌的Java代碼把這個查詢結果展現給用戶。那麼,這個JSP應用程序遵循了MVC模型嗎?如果遵循了,哪部分是M,哪部分是V,哪部分是C?在MVC里,我想我比較理解的就是V。至於什麼是M,什麼是C,我真心不理解。比如我看網上的評論,有人說M是"數據模型",有人說是"業務模型",不一而足。我想這個M不能光是數據模型吧?還是說,這個"數據模型"與我理解的數據模型不是一個意思?因為,如果它只是用來說明數據格式的,那麼計算的邏輯究竟存放在哪裡?好,那麼先按我的理解,假設V就是JSP頁面,M就是數據+計算,那麼C呢?在我這個例子中,C的功能是分布在初始頁面和servlet之中么?還是說只包含servlet?說到底,C到底是幹什麼用的?我大體上明白,但是總覺得又抓不住重點。有人說,C是根據用戶的請求選擇合適的M和V,僅僅是這樣么?另外,我還是不能很好地理解為什麼大家要反覆提及MVC模型。或者說,能不能給我個例子,說明MVC模型為什麼在Web應用程序開發中如此重要?如果不遵循它,會產生什麼嚴重的後果?代碼耦合在一起不好維護?比如,在我上面的那個例子中,就算我不遵循MVC模型,又能怎麼做?讓servlet直接處理業務邏輯?或者在結果頁面里用內嵌的Java代碼處理業務邏輯(查詢資料庫)?嗯,這樣說起來似乎是不太好,但是它產生的後果真的很嚴重么?
重新整理一下,改動比較大。
這個問題其實本身很簡單,主要是同一個詞用在不同語境下,所以造成了表達不清。MVC 三者中,Model 是核心。
Model,也就是模型,是對現實的反應和簡化。你對問題的本質的描述就是Model。解決問題就是給問題建立Model。
比如我們在現實中收發郵件的過程是什麼樣的?寫好郵件,加上收信人地址,丟到郵筒。過幾天去看看郵箱里有沒有回信。地址不存在信會被退回來。
你看這是不是和電子郵件的使用過程一樣?無非就是把現實中的過程簡化之後,搬到計算機上了而已。模型描述本質問題,忽略細節。
當我們關注業務問題時,只有描述 「用戶所關心的問題」 的代碼才是 Model。當你的關注轉移到其他問題時,Model 也會相應發生變化。失去了解決特定問題這一語境,單談 Model 沒有意義。
對於想收發電子郵件的普通用戶來說,電腦加網線就是 Model 。想發電子郵件?買台電腦,裝上網線,問題就解決了。
View,也就是視圖/視野,是你真正看到的,而非想像中的 Model。
Controller,也就是控制器,是你用來改變 Model 方式。簡單的說 Controller 和 View 分別是 Model 的 輸入 和 輸出。還是剛才的例子,想收發郵件,光有電腦 (Model) 還不行。
你知道你的郵箱在電腦里,但是你不知道它是什麼樣子。所以你還需要一台顯示器 (View)。同時,你可以看到你的電腦在運行,你的郵箱在收信。但是你還想發信,你需要一塊鍵盤 (Controller)。
大家不要看到 Controller 有個 -er 就以為 Controller 一定是人。我們平時玩遊戲的手柄也叫 Controller 。Cooker 也有 -er 呢,但它的意思是「廚具(灶)」而非「廚師」。Ruler 也有 -er,但它也可以指「尺子」。
說到底,View 和 Controller 可以是 Model 的一部分。為人么要單獨把他們跟 Model 分開呢?因為 View 和 Controller 是外在的東西,只有 Model 是本質的東西。外在的東西天天變化,但很少影響本質。把他們分開比較容易維護。
比如同樣是跑 Android 系統的電腦,可以做成手機,可以做成筆記本,還可以做成機頂盒。無非就是 View 換成顯示器,液晶屏,還是電視機,Controller 換成觸摸屏,鍵盤,還是遙控器的問題。本質上其實是同一個 Model (Android 電腦)。
現在回到 Web 開發的話題。你最關心什麼問題呢?
顯然,對於不同的人,關心的問題是不同的,對他來說Model也不同。
從資料庫管理員的角度上看,你的資料庫整個就是一個 Model。很顯然,資料庫的數據變化已經反映出了用戶所關心的一切。在資料庫管理員的眼中,你的Servelet 整個就是一個大Controller,就是把用戶的請求轉換成資料庫查詢而已。由於 Model 沒有邏輯,所以整個就像一塊橡皮泥,想怎麼捏,就怎麼捏。所以如果你得寄希望於一雙靈巧的手(Controller),才能避免犯錯。但手本質上是不適合重複性勞動的,所這種Model未必合適所有問題。
寫後台的人為了解決這個問題,只好再把資料庫包裝一層,即通過所謂的業務邏輯對象來讀寫數據。然後這些業務邏輯對象就成了Model。當然資料庫管理員可能會說,我可以有邏輯啊,你可以寫存儲過程嘛。
也有人覺得我自己建自己的Model,資料庫只管存數據就行了。所以他們傾向直接把對象序列化丟伺服器,或者用對象資料庫。
還有些人妥協一點,認為資料庫也是有Model的但它是關係型(Relational)的Model,但我也有自己的面向對象(Object-Oriented)的Model,所以兩個Model之間需要同步。這就是ORM(Object-Relation Mapping)。
最後寫前端的人說,我做 View 也不容易啊。我要保存中間的輸入狀態,要做邏輯驗證邏輯等。在最終提交到伺服器之前,你總不能讓用戶中間輸錯一個數據,就重啟系統,整個步驟重來吧?你去銀行申請服務,還得填表(Submit a Form)呢,表個還要改好幾次呢。於是 View 也要有自己的 Model,這個特定的情形。
更有甚至者,你的 View 根本就不是你自己開發的。比如開發 視屏播放器 (View) 的人哪管你是幹什麼的啊?人家只關心你給他的東西是什麼格式的,這也是他的 Model,叫 ViewModel (MVVM里的VM)。
一般來說,Controller 做的工作都比較簡單,無非就是轉轉格式,做做驗證。甚至有時 View 的工作也很枯燥,比如輸出 JSON 或 XML。所以這些一般都由框架包辦了,你只要關注 Model 也就是 核心問題 就行。
為什麼 MVC 難?一個難點就是,你對你要解決的問題沒有一個清晰的認識,所以根本就沒有Model;另一個難點是,你沒有經驗的時候,不知道怎麼控制Model的粒度。你不找一個現成的MVC 框架 而要用servlet 自己來做,當然不會那麼清晰
以至於別的用過mvc框架人想告訴你什麼事情,所說出來的可能都是一些你沒聽過的概念,以至於溝通不能。
建議看下面的站點
https://msdn.microsoft.com/en-us/library/ff650511.aspx
, 這是2003年微軟為了在 http://asp.net 基礎上實現mvc 做的探討與說明。
那個年代http://asp.net還沒有MVC 產品,所以這個文檔剛好符合你現在的狀況 也就是落後了時代大概12年的狀況
從你給的例子來看,查詢的結果是model,顯示的頁面是view,在view中點擊查詢按鈕後執行什麼具體操作,以及查詢結果model如何通過view展示則是control的功能。所有mvx的設計模式都是通過x實現model和view的解耦。在mvc中這個x是control。
謝邀。
首先,你給的例子硬要拆成三部分也不是不可以,但是……就倆頁面的小東西,還 M 個啥 VC 嘛(MVC 好歹是個「架構」,架構二字會尋短見的~ 其實你的例子里不需要 C,見後面解釋)。
Web 開發不一定要遵循 MVC 模型,甚至現代 Web 應用開發越來越不適合 MVC 模型。而且,不同應用情況下,MVC 的形態會天差地別。脫離應用環境談 MVC 是沒有意義的。
回到正題,我覺得題主之所以覺得 C 不好理解,很大程度是「控制器」這個詞本身表意不明所致。我當初就想:- 一個應用的控制者當然應該是用戶啊,程序裡面冒出個 Controller 是鬧哪樣?(有興趣可以看那篇著名的「名詞王國的死刑」Stevey"s Blog Rants: Execution in the Kingdom of Nouns)
- 如果參照電視遙控器來理解,C 光負責用戶的輸入(對應各種「Action」),那為嘛不叫 router?程序里搞一堆 Controller 文件只是完成 router 的作用不是很傻么?
- 如果不理解為遙控器,主語「控制者」算是個幽靈,那「控制」的賓語是 Model 是吧,那 Model 還控制 View 呢,憑什麼 Model 就不是「Controller」?
好在那時候單頁應用還不太流行,否則沒有了那麼多對應 URL 的 action,用戶輸入都成了 JS 事件,Controller 就更加流離失所了。
~~~~~~~~~~~~~~~~~~~~~
但作為一個大學時代寫過各種留言板、教務系統和資產管理系統的碼狗,我很快發現了 C 的存在價值:用於彌合「需求」和「模型」的縫隙。
在架構一個應用時,我們要建立模型,說得土一點就是建表,然後設定對這些表的各種可能操作。比如建一個 students 表,允許關聯班級、導師,然後定義增刪改查的操作,別搞出漏洞或者臟數據……這些事情完成,我們就實現了「領域模型」或者說「業務邏輯」(domain logic/business logic)。
但我們沒有辦法根據「需求」直接架構這些 Model。需求是多變的,甚至是感性的、碎片化的。而「Model」需要實打實地對應一個面向對象編程意義上的「對象」,追求單一性、里氏可替換、介面分離、開閉原則……一堆原則。
在現實中,我們不可能對「需求」使用「單一性」原則。用戶打開一個知乎用戶頁就想看到他贊過的帖子他發表的回答;打開一篇網易新聞就想看腦殘評論;打開一本文藝作品就想聆聽習總在文藝座談會上的講話……如果把各種需求都塞到模型里,會產生大量冗餘和重複的代碼。
此外,對象之間天然不擅長走「工作流」,所以涉及「提交了 A 然後進入 B 頁面」這種應用層面的流程需求,也很難用 Model 對象表達。
何況,需求之間也是存在「繼承」的,比如一個網站的一大波頁面都需要展示用戶的登錄信息和頭像。這種數據如果你不想在 V 裡面直接讀 Model 的話,就只有靠 C 之間的繼承來傳遞了。
如果一個應用同時有網站、移動 APP 和 API 介面就更容易理解了,Model 在不同應用之間應當是可以復用的,因為它走的是「業務邏輯」。
所以,我們不妨把 C 理解為「用戶需求的一種抽象」。除了負責傾聽用戶,還負責給用戶所有他需要的數據(這有些接近 ViewModel 的概念了)。這部分東西,其實也被稱為「應用邏輯」(application logic)。
如果應用是個 RESTFul 的 API,那可能幾乎沒有 C,因為它的「用戶」非常「理性」(同理,題主的例子需求是既簡單又單一的「查庫」,夠理性,C 也沒啥用)。但對於 RSS,C 可能又是必要的,但依然幾乎沒有 V。對於報表應用, CMS,SNS,管理後台……不同形態的應用,MVC 的情況會是天差地別。
另外:
雖然題主覺得「對 V 比較理解」。但 View 可能恰恰是 Web 程序最難說清楚的地方。按上面對 MVC 的定義,M 和 C 的分野在業務邏輯(domain logic/business logic)和應用邏輯(application logic),而 View 僅僅是視圖。
但在 Web 領域裡已經沒那麼簡單,由於前端越來越多地承擔了應用邏輯的功能(畢竟用戶輸入都是綁定在 DOM 上的),所以承擔「用戶和系統之間連接」的更多是 View。這時 View 其實是「控制項」而非「視圖」了( @winter 老大語:Web前端開發:為何選擇MVVM而非MVC)。俺不是理論派,以上說法主要基於個人有限經驗,如有偏頗敬請指正。MVC是一個對有UI要求的軟體工程的模塊化架構方式。不同的MVC有著各模塊在邊界上的差異,不過大體還是可以把握的。你似乎對於M和V的邊界感到最困擾,我的看法是大部分框架目前都按照面向對象的方式來設計數據結構,數據對象本身可以擁有的行為可以視作M,比如判定用戶註冊名是否合法這種邏輯。而更加複雜的,從邏輯上來說不是單一對象所應該具有的行為的操作,則屬於C的範圍。
放大一些說,很多框架幫你做了的東西,比如DBC,ORM等都屬於M,請求的接收處理等都屬於C,模板和動態生成頁面等也都屬於V。我來講一講,那些年我和MVC不得不說的故事吧。
還記得第一次寫程序是在內蒙古包頭,那一年正在舉辦奧運會,我從來沒寫過程序,因為偶然的原因參與到一個項目里,去到鹿城,見識了所謂的長河落日、大漠孤煙。
項目一共四人,我最弱,什麼都不懂,PM既管項目又管技術,當時,他告訴我,你什麼也不需要做,你要做的就是每天坐在工位上,假裝很繁忙的敲著鍵盤就可以了,如果你願意學,我也會教你一點。這時候我們用的PHP,來包頭之前我從未寫過程序,當然也就沒聽過什麼PPP。當時,我不會知道這位PM會是我職業生涯里遇到的為數不多的好領導之一。
我必須願意學啊!他先叫我寫幾個簡單的頁面,做對Mysql資料庫的增刪改查,其時,我連mysql安裝都是第一次,但藍天白雲映照下的包頭軟體園特別適合學習,然後他又叫我上網找一些分頁插件,看能不能把查出來的數據分頁顯示,之後他又告訴我,他自己寫了一個簡單的分頁庫(對他崇拜極了),讓我自己去學著用,後來他說這個分頁庫里用到了面向對象的思想,我對此全然不懂,但總算是能自己寫幾個頁面實現完整的數據讀寫操作了,而這麼多年以來,我才漸漸明白,那其實真的可能就是一切,幾乎所有的web技術都離不開數據的增刪改查,而當時我已經朦朦朧朧地學會了。
如果只是這樣,我就不會遇見MVC。再後來,很意外地,他不再讓我假裝敲鍵盤,我開始幫忙寫一點簡單的頁面,然後我就遇到了smarty+extjs,很幸運,我一開始學web技術就遇到這兩個名不虛傳的技術框架。smarty是一個模板引擎,extjs是一個前端js框架,對於當時的我來說,就是用smarty操作資料庫的時候不用去理會extjs,而寫extjs的時候只需要查它自己的文檔就足夠了,而它們是如何聯繫在一起的,完全不用關心。另外,extjs在這個時候才1.X版本,還不像今天使用地這麼廣泛,而我的PM已經開始讓我們學習了,這不能不說是幸運。在接下來的一個月,我不時地在smarty和extjs之間切換,因為做的都是小修小改,不需要掌握整個應用程序的框架,所以也就樂在其中,只記得後來終於要回學校的時候,PM告訴我說:你以後應該去看看MVC。天蒼蒼,野茫茫,我記住了這句話。
如此幸運,我帶著PM送給我最後的忠告離開了包頭,回學校開始選課,這學期學校開了一門JAVAEE高級開發的課程。我知道我和PHP的緣分已盡,從此開始了JAVA修行之路,但MVC這個名詞卻深深地印在了我的腦海里。
J2EE課的老師是學校從外邊請來的一位非常漂亮的女培訓師,她沒有先教我們jsp,而是一開始就只講servlet,從servlet的API到http的GET/POST方法,她對這些概念的理解,以及課堂上的編碼演示,讓我迅速地開始喜歡上了寫web程序的感覺。然後,她說jsp最終都會被編譯成servlet運行,接著又講了EL表達式、jsp標籤、國際化,而這些都是理解web MVC中的V非常重要的概念。
接下來的事情就像至尊寶所說的峰迴路轉,我第一次見到了MVC。
老師開始講struts2,她說她不打算介紹struts1,因為已經過時了,而她自己也認為struts2是一個非常好的框架,更重要的是,這是一個強制MVC的框架!什麼意思呢?就是如果你的程序用了struts2,那麼你已經使用到了MVC模式。現在,我知道這麼說既對又錯,因為MVC並不是只針對前端。使用struts2之後,頁面上的數據與後台之前的傳輸都靠框架來完成,頁面邏輯自然有struts2的標籤來幫忙實現,而後台只要實現struts2既定的介面,在介面方法中完成業務邏輯即可,這不僅讓我想起了曾經的smarty和extjs。多麼相似的手法!多麼熟悉的場景!
web技術就是一條不歸路,在這條路上,你一開始感到陌生,感到雜亂無章,感到困惑,可是越往後走,越發現原來一切都像是希臘神話中的西西弗斯。
學完struts2之後,老師又緊接著講了hibernate2.X,最後因為時間關係,把最重要的spring留給了我們自己。學期結束,我帶著對MVC的新認識和對Spring的憧憬,進入了新的一年。
新的一年就像是霍比特人的五軍之戰,無數的框架和技術向我奔襲而來、應接不暇。我先學習了spring,可是沒等我學完,spring出3了,於是又跑去熟悉spring3,真的是禍不單行,這時我聽到一個不好的消息,據說struts2快被淘汰了,而spring這個東西想要當java web技術里的霸主,於是我開始學習spring mvc和spring data。同時,我又知道了velocity,jquery,ibatis,在接下來的兩年時間裡,不斷在各種框架之間切換,偶爾還回到PHP里看一看那些老朋友,也似乎在這個時期,我的技術進入了瓶頸。
急著找工作和急切需要突破的我開始複習各種概念,這時設計模式進入了我的視線。上J2EE課的時候,老師推薦了《Head first jspservlet》,恰巧此時,我開始讀《head first design pattern》,這時我發現了一個奇怪的問題,MVC不會被歸到24種設計模式里,而專門講設計模式的書也沒有特別講MVC模式,但當我們提到MVC的時候,往往會在後面加一個模式?這時為什麼呢?到底什麼才叫模式?
恰逢其時,我開始讀《建築的永恆之道》,而模式正是永恆之道的一種體現,並不是說某個模式一定會永遠流行,但在一段時間內,某個相似的框架或輪廓或手法或組合一定可以復用。也即模式是可以復用的。顯然,從這個意義上講MVC是可以復用的,但具體怎麼用,卻沒有說。
而當我到公司實習,參加各種項目,畢業工作之後,以前的技術似乎全都消失了,MVC漸漸淡出了我的視野,然而又隱隱覺得不對,和同事討論前端該用什麼框架好,有沒有license問題,各有什麼優點,向後台傳輸數據會不會麻煩,而到了後端,我們又在計劃里加入了對各種資料庫的調研,雖然參與了很多開發任務,最核心的部分往往不是我在寫。終於畢業一年多,我在一個項目里開始選擇框架,當時用了groovy這種語言,而所用的框架則是grails,這一用才發現,原來MVC一直在我們身邊。
當我們討論前端框架的時候,其實已經被MVC的力量所隔離,正是因為當時的程序使用了MVC,才可以讓我們自如地切換,而後端對資料庫的操作也是如此,用grails的時候,還發現,好久沒有自己學習流行的框架技術,而當前最流行的的就是ROR,我不會ruby所以沒有學,但仔細調研後發現,幾乎所有其他web語言里都有rails風格的框架,也就是convention over rule,struts2有插件,python有類似框架,連新語言grails也完全就是rails風格的,所謂的MVC模式早就深深植根於rails風格的程序里了,如果說struts2是一個強制mvc框架,那麼rails風格的框架就代表MVC模式已經成為一種標準。
更神奇的是,我在這一年邂逅了extjs,這時她已經改名叫sencha。而這一邂逅,才發現她本身已經變成了一個MVC框架,而有類似功能的還有angularjs,她們都在一遍又一遍地更新我對MVC模式的理解。
在extjs4.X里,數據,業務邏輯和顯示層是分開的。她明明是一個前端框架,怎麼還會有業務邏輯和數據呢?而angularjs所要乾的事情就是綁定數據到html標籤,同時讓頁面邏輯只存在於angularjs中,而html標籤完全只用來顯示數據。這又是什麼意思?(我不打算在此解釋了。)歸根結底,我們發現,幾乎所有的應用程序都一定有至少兩個部分,甚至3各部分,一個是數據,一個是邏輯,如果存在第三個部分就可以叫做輸入輸出,程序接受輸入,進行處理,處理完成最終輸出處理結果,這就會有數據,就會有邏輯,就會有輸入輸出,數據和邏輯就對應了model,view對應著輸入輸出,而把這些連接在一起的各種「無意義的」調用就可以看做controller。事實上,我已經很久沒有寫過什麼web程序了,但如果從這個意義上看,MVC從未離開過,以前寫QT的時候有MVC,用MFC的時候更有MVC,而現在寫C++伺服器還是有MVC,因為真的只有用過的人才知道好。MVC從一個連接前後端的框架,逐漸前後延伸,到現在為止,我的理解是,有數據的地方就有MVC。
怎麼越寫越嚴肅了,差不多,遁了。以下都是我個人的理解
不同意 muye yang 所說的 Model層是 核心的說法……
C層才是核心,所謂控制器嘛……如果不是核心,何談控制?
——————————————————————
我們從一個較高的層面看待一個請求的流程的時候,
可以把 JAVA運行過程 看作是 其中的一個步驟。
而每個步驟,都是這樣一個過程:
- 接受前一個步驟的輸出
- 格式化輸入數據,為後一個步驟的標準格式
- 輸出處格式化輸入數據給後一個步驟
- 接受後一個步驟的輸出
- 格式化輸出數據,為前一個步驟的標準格式
- 輸出格式化輸出數據……
前一個步驟的輸出,就是後一個步驟的輸入。
在 JAVA運行過程 的輸入,簡化來說就是 瀏覽器輸出給伺服器的內容
——(NGINX之類的中間層先不考慮了……)——
而去資料庫取數據時,一條SQL就是我們給資料庫的輸出,對資料庫來說就是輸入。
而資料庫返回給我們的數據,就是資料庫對輸入進行邏輯處理之後的輸出……
————————————————————————————————————
MVC模型中,M層對接後一步驟,V層對接前一步驟的輸出,C層核心處理其他事情。
後端代碼,可能要調用 多個 後一步驟(資料庫/緩存等),
因此 M層中 每個模塊都只負責自己的一部分內容……
所以 C層需要 將 輸入數據 處理成 對應M層 可以接受的數據格式
——看到這裡是不是又像是 上面的6步了? 其實是一樣的——
而M層接收到資料庫返回的數據,也需要格式化成C層需要的數據,再返回C層
而V層,則是將C層輸入自己的數據,格式化成 前一步驟(HTML/JSON等)接受的數據格式
————————————————————————————————————
現成的MVC框架里,其實不僅僅是 MVC三層。
一般來說,輸入數據 都會先過 路由,以調用對應的C層
那麼 這裡是不是可以稱為 R層 ?
輸出數據到 瀏覽器/資料庫時 ,要不要鏈接資料庫?
要不要叫 D層?(當然一般這個就包含在M層的概念里了)
而一些邏輯比較複雜的應用,因為 M層和V層 功能相對簡單,C層會比較大,
因此,還會提出 Service層 ,Agent層 進行處理
————————————————————————————————————
不管是 MVC 還是 RDSA ……
歸根結底,都是一種 對代碼運行流程中的步驟進行抽象 ,而得出的 抽象的概念。
因為對每個步驟的定義的不同,抽象而成的概念,雖然可能有同一個名字,
但是其具體的意義,就可能完全不同了 ……
什麼是MVC模式?
Model: 組織並儲存數據, 根據Controller的指令準備好數據View: 根據用戶的指令, 通過一種合適的方式展示數據Controller: 接受用戶指令, 讓Model更新數據, 告訴View如何更新界面.OK...這個晦澀的翻譯我也是念得舌頭都酸了. 現在假設你去星爸爸裝B...在一個陽光明媚的午後, 你跟千千萬萬的小白領一樣來到了銀河SOHO附近的星巴克. 你徑直走到一位棕圍裙的咖啡師面前:"您好, 給我來一個中杯的拿鐵""您要的是這個么?" 咖啡師指著Tall的杯子微笑地問道"嗯, 這個中杯" 你指著Grande的杯子說道"對不起先生, 那個是大杯, 這個才是中杯" 咖啡師繼續保持尷尬而不失禮貌的微笑, 指著Tall的杯子說道"你這不是大中小三個杯子嗎? 我要這個中杯" 你覺得自己理直氣壯"對不起先生, 那個是大杯. 這才是中杯...中杯, 大杯, 特大杯" 咖啡師指著Tall, Grande, Venti解釋道好了...你不是羅永浩, 你也不用扇自己幾個嘴巴子.重點是在剛才這個情景里, 你是User, 你點的中杯拿鐵就是你的User Request.對咖啡師來說, 一杯拿鐵真是low爆了, 根本無法展現其棕圍裙的功力. 不過是這麼幾步:1. 用濃縮咖啡機把咖啡豆磨成粉2. 加熱牛奶打奶泡3. 把磨碎的咖啡粉放入過濾斗里, 鎖在沖煮頭上4. 按下double選項, 製作一杯濃縮咖啡5. 把牛奶倒入濃縮咖啡中並按心情決定是否拉一個花6. 把咖啡遞給你咖啡師的大腦里存儲著這些步驟, 她的腦瓜子就是Controller.只要你點的飲品(User Request)是她能理解和製作的, 她就可以立即開始工作.如果你非搗亂, 來星巴克點豆汁, 咖啡師(Controller)無法理解你這個User Request, 就會報錯(比如返回503/404)咖啡師沒法給你做豆汁的原因除了味兒太大以外, 更重要的是他的工具和材料有限.咖啡師有限的工具和材料就是Model, 包括下面幾種東西:* 賊老貴的濃縮咖啡機* 非洲哥倫比亞高萃取精華貓屎咖啡豆* 流奶(這可能是個[n][l]不分的咖啡師)* 分不清大中小還是特大大中的咖啡杯* 咖啡師一會如蘿蔔一般一會如青蔥一般的雙手在一家星巴克里, 所有的材料都是共享的。你換一個咖啡師還是可以給你做同樣的拿鐵.類似的,即使來一個黑圍裙咖啡師, 他也做不了豆汁, 因為沒有那些原材料.最後, 你拿到手裡的, 看得見摸得著可以喝的這杯拿鐵就是View.這杯咖啡(View)是從有限的材料(Model)里來的, 並由咖啡師的大腦(Controller)精心組織和安排並製作的.同樣的原料也可以作出不同的咖啡比如美式比如摩卡比如卡布基諾: 同樣的Model通過Controller可以組織成不同的View.奇思妙想:* 想再來一杯? 你看著你空空如也的咖啡杯(View)是沒有任何作用的. 你只能再跟咖啡師要一杯(another User Request)* 咖啡師接到你的order之後到給你端上咖啡的時間肯定是越短越好. 這就告訴我們Controller應該maintain很少的logic. 一個NB的咖啡師可能在每天開門之前就把原材料都準備好.* 咖啡師能不能直接把咖啡粉和牛奶倒到你嘴裡然後攪一攪讓你喝下去? 行是可行但是可能會造成星巴克流血事件. 咖啡師還是應該在吧台後面把咖啡做好後再端給你. 這就告訴我們View不應該contain太多的logic回到Web Development:1. 用戶發送了一個Request, 比如"/home"2. Controller接到這個Request, 會發出一系列的指令: 比如讓Model執行一些操作或者更新某個View3. Model接到Controller的指令, 去資料庫里拿出一些數據返回給Controller4. Controller接到數據, 更新了"/home"的頁面5. 用戶看到了這個頁面Ref: https://medium.freecodecamp.org/model-view-controller-mvc-explained-through-ordering-drinks-at-the-bar-efcba6255053
你可能也喜歡:
java中的繼承,多態,抽象,大家是怎樣去形象的理解的?
我來談談我對於mvc的理解,如果說得太淺請大神們輕輕噴。
你所舉的例子不是只用servlet來做的,應該是jsp+setvlet。以題主的登錄為例,詳細說說,不懂的繼續補充。 jsp當初就是因為在servlet中拼html代碼太麻煩而開發出來的技術,因此jsp一般用於對於頁面的處理,也就是view的部分。jsp上進行登錄操作時,通常用一個表單進行,用戶在表單中填寫了用戶名密碼,然後點擊提交。這時候,比較典型的操作是將這些信息交給程序員寫的servlet(LoginServlet)進行操作。(題外話,有時會寫ajax進行動態校驗啥的,不考慮不考慮)而servlet中的代碼更多的是對jsp中的一些控制方面的或者業務邏輯進行操作,一般小型的web開發會將jsp頁面提交或者跳轉後交給一個servlet進行業務邏輯處理。相當於control的部分。LoginServlet接收到jsp傳來的用戶名密碼,在資料庫中進行查詢,並且返回需要的結果。通常我的操作是寫一個dao層,LoginServlet調用dao層LoginDao的方法查詢資料庫。而m的部分,更多是資料庫一類的操作,比如說,你需要將一些用戶的信息持久化到硬碟中,可以通過資料庫對這些信息進行管理。而對於資料庫的處理,增刪改查,事務管理,由一個dao層來進行,也有相關的工具,hibernate等等。。你也許會問,幹嘛拆開來進行處理,多麻煩。分開進行處理其實你可以理解成人類分工的結果。一個項目可能是由若干位程序員進行開發的,如果所有代碼混合起來,不好分工。另一方面,也是為了網站的更新進行的劃分。舉個例子,到了新年的時候網站界面部分進行一些改進,換上紅色元素,這時候在mvc模式下,網站只需要改動的時view部分的效果,而業務邏輯等等不需要再進行改動。推薦看看spring MVC框架,應該很標準吧,
MVC是軟體工程界裡面最大的一個坑,因為當初Smalltalk原創這個概念的時候,根本就沒有詳細說M怎樣V怎樣C怎樣,以至於後人想像發揮的餘地實在太多。
當然這個其實是正確的,構架這種東西,應該與時俱進,因地制宜。所以說只有念歪經的和尚,沒有歪的經。推薦閱讀:
※Nodejs中,我將資料庫連接後的實例對象放在global全局對象中,這樣合理嗎?
※Web 前端和後端工程師的具體職責分別是怎樣的?
※想深入了解 HTTP 協議,有哪些值得推薦的書籍?
※零基礎學習Web前端開發應該先學什麼?
※用python+flask搭建一個博客需要學習哪些知識?