1. 程式人生 > >MVVM模式原理分析

MVVM模式原理分析

親愛的博友們,感謝來到Darren的部落格

很久之前就想抽時間研究一下mvvm設計模式,相對於MVC,MVP設計模式之後,MVVM在WPF和SL開發中得到了廣泛的使用。直接進入主題:

1, 前提
可以說MVVM是專為WPF打造的模式, 也可以說MVVM僅僅是MVC的一個變種, 但無論如何, 就實踐而言, 如果你或你的團隊沒有使用"Binding"的習慣, 那麼研究MVVM就沒有多大意義. 另外,個人覺得, 使用Command以及打造一種合理的簡化的方式去使用Command也與使用Binding一樣重要.

2, 誕生
為了解決現實世界中的問題,我們需要將現實世界中的事物加以抽象, 然後得到了Domain Object, 無論貧血的還是富血的, 我們都可以簡單地把他們歸結為"由現實世界抽象出來的模型", 也就是我們的model, 也就M-V-VM中的"M"。


但其無法與我們的使用者進行互動, 所以, 我們需要為其建立一個介面(檢視, View), 該檢視可以與使用者輸入裝置進行互動, 這很棒, 但問題是如何將View與我們的model關聯起來? Binding便可以發揮作用了, 比如檢視上的某一個文字框中的文字和Model中的"使用者名稱"關聯起來, 使用者便可以通過操作該文字框來訪問和修改Model的"使用者名稱"了。


這是極其簡單的情況, 但實際程式設計時我們發現, Model中的屬性(與方法)往往不那麼容易與View中的介面控制元件關聯起來, 比如, "型別不匹配": 介面控制元件所需要的型別與模型中屬性提高的型別不匹配. "需要額外操作": 模型中的資料需要經過一些額外的處理才能傳給檢視,反之亦然. 此時, 我們意識到View似乎需要一個"Helper"類來處理一些額外工作. 這 個helper所包含的程式碼可以放在除了Model外的很多地方(我們現在不考慮貧血富血之類的爭論), 比如View中, 記得自己剛學習窗體程式開發時就是這麼幹的, 將絕大多數處理邏輯放在那個所謂的CodeBehind中. 後來,正如大家在各種設計模式書籍中所看到的一樣,為了將View和Model剝離開來,實現view可替換(比如你可以講自己精心設計的軟體同時運行於 窗體程式,Web甚至Mobile上), 便有了MVC. 有了MVC以後似乎就開始滋生M-V-XXX之類的爭論與變種模型, 比如MVP以及這裡的MVVM,甚至MVP也有著Supervising Controller與Presentation Model兩種方式. 但主要圍繞兩個問題,一是model與view之間的關係, 完全隔離的?單向的還是雙向的? 二是這個"XXX"需要完成哪些功能,簡單流程排程?複雜規則處理? OK,這些爭論都沒有關係, 是否採用某種模式取決於你的開發所處的環境(比如語言特性,框架特性)以及你的業務特性以及所面臨的主要變化點等等。


但與MVC,MVP所不同的是,MVVM的引入不僅僅是技術上的原因(解除耦合應對變化等老生常談),另外一個很大原因是:軟體團隊開發方式的改 變.如果你做過一段時間的WPF專案開發的話,你可能會有比較明顯的感覺:在View層打造上,如何
分配程式設計師和美工的工作.在繼續閱讀之前,大家可以看 看我以前的一篇文章"在UI Designer與Developer之間". 以前我們團隊採用的便是"整合模式", 我便兼職了其中的"Integrator"角色.這還不錯.但說實在的,這僅僅是一個在特殊情況下不得已而為之的暫時方案,所以我們付出了很大的努力開始 轉向"收割模式"了,要轉向這個模式,至少需要兩個基本條件:
(1)你擁有能夠熟練運用Blend等工具能為程式設計師輸出XAML的美工, 他專注於純粹的UI/UE, 另外他還必須具有一定的"程式設計師"思維.以便輸出的東西能很好地作為程式的一部分而運轉起來,而不是僅僅"看上去"是那樣的。


(2)你需要能夠脫離View層但仍能編寫出高質量程式碼的程式設計師。
幸運的是, 我們在努力創造條件1,並取得了很好的效果.(你可以招一個具有Flash指令碼編寫經驗的並且有極大的學習熱情的美工人員, 並對他進行Blend的相關培訓). 而MVVM模式為我們實現第二個條件提供了極大的便利. 為什麼MVC/MVP模式不行而MVVM可以呢? 很簡單, 在MVC和MVP模式中, View層都具有很多程式碼邏輯, 開發View層的是程式設計師, 雖然UI/UE團隊會做很多工作, 但這個層的"實現者"仍然是程式設計師. 在以前的開發中,其工作得很好, 而在WPF開發中程式設計師對View層的展現顯得力不從心了,美工(指符合上面條件1的美工)雖然很擅長, 但他會說"可惜我不會程式".於是, 我們需要一種方式將View層的程式碼邏輯抽取出來,並View層很純粹以便完全讓美工去打造它.相應地, 需要將View層的相應邏輯抽取到一個程式碼層上,以便讓程式設計師專注在這裡。


回想一下, 我們只所以要在View(Xaml)背後寫一些程式碼(C#), 無非是想傳遞一些資料以及傳遞資料時的資料的處理或在使用者與介面控制元件進行互動時執行一些操作, 最簡單的例子是在MVC中當介面發生互動時View去呼叫Controler中的某個方法, 以便將該操作的相應"指示"傳遞到"後臺"去. 在以前的技術中, 這樣的"銜接性"的程式碼是必須的. 而在WPF中, 則可以通過另外的技術來進行層與層之間的"銜接", 這就是"Binding" 和"Command", 以及稍後我們會提到的"AttachBehavior". 通過Binding, 我們可以實現資料的傳遞; 通過Command, 我們可以實現操作的呼叫.(AttachBehavior的作用稍後再談). Binding和Command是可以寫在XAML中的, 這樣看來XAML後面對於的CS檔案可以被完全拋棄或不予理會了. 這樣的XAML檔案正是美工所需要的. 而這些對於Binding以及Command的定義描述以及其他相關資訊的程式碼應該放在那裡呢, 當然不是View, 更不是Model, 是"ViewModel". ViewModel是為這個View所量身定製的, 它包含了Binding是所需的相關資訊,比如Converter以及為View的Binding提供DataContext, 它包含了Command的定義以便View層可以直接使用, 另外,它還是一個變種的Controler, 它得負責業務流程的排程。
於是, 便有了這副圖, 然後, 正如"時勢造英雄"所言, MVVM就誕生了.