深入淺出MVC框架模式


深入淺出MVC模式

 

一、MVC模式概述

模型-視圖-控制器(MVC模式)是一種非常經典的軟件架構模式,在UI框架和UI設計思路中扮演着非常重要的角色。從設計模式的角度來看,MVC模式是一種復合模式,它將多個設計模式在一種解決方案中結合起來,用來解決許多設計問題。MVC模式把用戶界面交互分拆到不同的三種角色中,使應用程序被分成三個核心部件:Model(模型)、View(視圖)、Control(控制器)。它們各自處理自己的任務:

(1)模型:模型持有所有的數據、狀態和程序邏輯。模型獨立於視圖和控制器。

(2)視圖:用來呈現模型。視圖通常直接從模型中取得它需要顯示的狀態與數據。對於相同的信息可以有多個不同的顯示形式或視圖。

(3)控制器:位於視圖和模型中間,負責接受用戶的輸入,將輸入進行解析並反饋給模型,通常一個視圖具有一個控制器。

MVC模式將它們分離以提高系統的靈活性和復用性,不使用MVC模式,用戶界面設計往往將這些對象混在一起。MVC模式實現了模型和視圖的分離,這帶來了幾個好處。

(1)一個模型提供不同的多個視圖表現形式,也能夠為一個模型創建新的視圖而無須重寫模型。一旦模型的數據發生變化,模型將通知有關的視圖,每個視圖相應地刷新自己。

(2)模型可復用。因為模型是獨立於視圖的,所以可以把一個模型獨立地移植到新的平台工作。

(3)提高開發效率。在開發界面顯示部分時,你僅僅需要考慮的是如何布局一個好的用戶界面;開發模型時,你僅僅要考慮的是業務邏輯和數據維護,這樣能使開發者專注於某一方面的開發,提高開發效率。

MVC模式淺談

圖1.1MVC模式結構圖

如圖1.1所示,視圖中用戶的輸入被控制器解析后,控制器改變狀態激活模型,模型根據業務邏輯維護數據,並通知視圖數據發生變化,視圖得到通知后從模型中獲取數據刷新自己。

 

二、深入解析MVC模式

對MVC模式有了一個初步的認識之后,我們可以繼續深入地了解它。MVC模式的關鍵是實現了視圖和模型的分離。這是如何實現的呢?MVC模式通過建立一個“發布/訂閱”(publish-subscribe)的機制來分離視圖和模型。發布-訂閱(publish-subscribe)機制的目標是發布者,它發出通知時並不需知道誰是它的觀察者。可以有任意數目的觀察者訂閱並接收通知。MVC模式最重要的是用到了Observer(觀察者模式),正是觀察者模式實現了發布-訂閱(publish-subscribe)機制,實現了視圖和模型的分離。因此談到MVC模式就必須談到觀察者模式。如圖2.1所示。

MVC模式淺談

圖2.1 觀察者模式

觀察者模式:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。

圖2.1中Subject我們稱為主題,Observer稱為觀察者。主題提供注冊觀察者、移除觀察者和通知觀察者的接口,這樣只要觀察者注冊成為主題的一個觀察者的話,主題在狀態發生變化時會通知觀察者。觀察者有一個更新自己的接口,當收到主題的通知之后觀察者就會調用該接口更新自己。如何實現注冊和通知的呢?如果是用C++或java的話,主題就需要有一個觀察者鏈表,注冊就是將觀察者加入到該鏈表中,移除則是從該鏈表中刪除,當主題狀態變化時就遍歷該鏈表所有的觀察者通知它們更新自己。在c#中可以通過委托實現注冊。

       觀察者模式中的主題就對應於MVC模式中Model(模型),觀察者就對應於MVC模式中的View(視圖)。視圖向模型注冊成為觀察者,模型(主題)變化時就通知視圖(觀察者)更新自己,但是還有一個問題,我們如果不引入控制器的話,直接將接受用戶輸入並解析輸入操縱模型的功能放到視圖中的話會產生兩個問題:第一、會造成視圖代碼變得復雜,使得視圖就有了兩個責任,不但要管理用戶界面,還要處理如何控制模型的邏輯,有違單一責任的設計原則,一個類應該僅有一個引起它變化的原因,如果一個類承擔的責任過多,就等於把這些責任耦合在一起,一個責任的變化可能會削弱或抑制這個類完成其他責任的能力,這種耦合會導致脆弱的設計,當變化同時面臨兩個或多個方向變化時設計會遭到意想不到的破壞甚至根本沒辦法處理。第二、會造成模型和視圖的緊耦合,如果你想復用此視圖來處理其他模型,根本不可能。於是把控制器從視圖中分離出來,將視圖和模型解耦,通過控制器來保持控制器和視圖之間的松耦合,使設計更有彈性和容易擴展,足以容納以后的改變。

控制器相當於是視圖的行為,我們還要考慮到今后可能面臨的變化,例如視圖想換一種行為,我們是否做好了應付這種變化的准備呢?我們不應該將視圖和控制器緊耦合,例如不要一開始就將視圖和某一個具體行為綁定起來,這樣會使視圖更換行為的時候變得很困難,我們應該能動態的給視圖指定一個行為,用多態使視圖和控制器之間松耦合,可以使視圖輕松地更換行為,於是策略模式登場了,策略模式正是用來解決這個問題的。如圖2.2所示。   

       策略模式:定義了算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓算法的變化獨立於使用算法的客戶。

       MVC模式視圖和控制器實現了經典的策略模式:視圖是一個對象,可以被調整使用不同的策略(行為),而控制器提供了策略(行為)。視圖想換另一種行為,換控制器就可以了。視圖只關心系統中可視的部分,對於任何界面行為,都委托給控制器處理。使用策略模式也可以讓視圖和模型之間的關系解耦,因為控制器負責和模型交互來傳遞用戶的請求。對於工作是怎么完成的,視圖毫不知情。

MVC模式淺談

 

圖2.2策略模式

三、MVC模式的應用

       GOF四人組提出MVC模式的主要關系是由Observer(觀察者模式)、Composite(組合模式)和Strategy(策略模式)三個設計模式給出的。當然其中還可能使用了其他的設計模式,這要根據具體場景的需要來決定。GOF四人組提出復雜的視圖可以根據實際需要用組合模式來實現,當然,也要注意避免過度設計,如果視圖的結構不復雜就沒必要采用組合模式了。我們和一個同事一起開發的項目中,UI框架的設計我采用了MVC模式,主要結合了Observer(觀察者模式)、Strategy(策略模式)、Command(命令模式)和Singleton(單件模式)。用戶界面不太復雜,因此視圖不需要應用組合模式,在界面的框架設計中,界面菜單、對話框、樹形控件和表格控件對應於MVC模式中的View(視圖),其中對話框采用了單件模式,保證一個類僅有一個對話框實例,並提供一個訪問它的全局訪問點。控制器位於視圖和命令對象或模型中間,將界面請求封裝成一個命令對象,命令對象執行控制器發送過來的命令,根據命令對象模型負責處理邏輯和數據。項目UI框架中采用Observer(觀察者模式)和Strategy(策略模式)使視圖和模型分離,並讓視圖能靈活地更換行為,在前面已有詳述,不再贅述,我要重點提的是我為什么要采用Command(命令模式)以及如何將命令模式嵌入到MVC模式當中。如圖3.1所示。

MVC模式淺談

圖3.1 命令模式

命令模式:將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤消的操作。

根據項目的需求:用戶可以通過工具條按鈕、菜單按鈕、對話框按鈕或鼠標右鍵等操作來執行同一項請求;支持取消和重做操作;很容易增加或更換新的命令請求。這些問題都可以通過命令模式來解決。命令模式可以使不同地方的按鈕或操作代表同一項功能,只需要讓它們共享響應具體Command子類的同一實例即可。還可以通過多態動態替換Command對象從而輕松地更換請求命令。Command的Execute操作可在實施操作前將狀態存儲起來,在取消操作時這個狀態用來消除該操作的影響。Command具體對象調用一個Unexecute操作,該操作取消上一次Execute調用的效果。執行的命令被存儲在一個歷史列表中。可通過向后和向前遍歷這一列表並分別調用Unexecute和Execute來實現次數不限的“取消”和“重做”。Command模式將調用操作的對象與知道如何實現該操作的對象解耦。Command可像其他的對象一樣被方便的替換和擴展。在菜單中增加新的調用命令時只要增加新的Command,而無需改變已有的類。我們將Command對象放到控制器中,控制器接收視圖的輸入並解析,將用戶輸入發送給Command對象,Command對象調用執行接口,然后在Command子類中將用戶輸入發給模型,模型執行邏輯維護數據,並通知視圖。視圖得到通知后獲取模型的新數據並更新自己。項目的界面框架采用這種MVC模式使得軟件變得靈活、易於擴展和維護。

 

四、結論

在軟件開發的過程中,開發人員最為擔心的是需求的不斷變化,而這些變化又不是開發人員所能控制的,因此,為了適應這些變化,就要使用設計模式。MVC模式在一個解決方案中綜合運用多種設計模式,是模式中的模式,按MVC模式的設計,一個模型可以表現為多個視圖,這樣可以減少代碼的冗余。模型返回的數據不帶任何顯示格式,因此這些模型也可直接應用於接口的使用。由於一個應用程序被分離為三層,因此有時改變其中的一層就能滿足應用的改變。一個應用的業務流程或者業務規則的改變只需改動MVC的模型層,而不會影響到視圖和控制器。不過,使用設計模式並不是一定就能得到一個好的設計,過分地使用設計模式會增加程序的復雜性和晦澀性,讓程序不易理解,從而降低了程序的易維護性。因此要避免過度使用設計模式,我們應根據面向對象的設計原則和實際情況綜合考慮我們的設計,從而設計出具有良好擴展性和易維護性的軟件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM