天天看點

Unity應用架構設計(1)—— MVVM 模式的設計和實施(Part 1)

<a></a>

<b>閱讀目錄</b>

<a href="http://www.cnblogs.com/OceanEyes/p/unity3d_framework_designing_get_started_with_mvvm_part1.html#_label0">初識 MVVM</a>

<a href="http://www.cnblogs.com/OceanEyes/p/unity3d_framework_designing_get_started_with_mvvm_part1.html#_label1">MVVM 設計模式在 WPF 中的實作</a>

<a href="http://www.cnblogs.com/OceanEyes/p/unity3d_framework_designing_get_started_with_mvvm_part1.html#_label2">MVP &amp; MVVM</a>

<a href="http://www.cnblogs.com/OceanEyes/p/unity3d_framework_designing_get_started_with_mvvm_part1.html#_label3">MVVM 設計模式在 Unity 3D 中的設計與實作</a>

<a href="http://www.cnblogs.com/OceanEyes/p/unity3d_framework_designing_get_started_with_mvvm_part1.html#_label4">小結</a>

談起 MVVM 設計模式,可能第一映像你會想到 WPF/Sliverlight,他們提供了的資料綁定(Data Binding),指令(Command)等功能,這讓 MVVM 模式得到很好的實作。

MVVM 設計模式顧名思義,通過分離關注點,各司其職。通過 Data Binding 可達到資料的雙向綁定,而指令 Command 更是将傳統的 Code Behind 事件獨立到 ViewModel 中。

在WPF中,你會像如下這樣去定義一個專門管理視圖 View 的 ViewModel:

同時在 View 中你需要使用 Binding 将 ViewModel 的屬性綁定和控件的内容相綁定:

值得注意的是,要實作 View 和 ViewModel 雙向綁定,我們的 ViewModel 必須實作 INotifyPropertyChanged 接口,由于 WPF Framework 讓控件監聽了 PropertyChanged 事件,當屬性值發生時,觸發 PropertyChanged 事件,是以控件就能自動擷取到最新的值。反之,當控件的值發生改變時,例如 TextBox 觸發 OnTextChanged 事件,自動将最新的值同步到 ViewModel 相應的屬性中。

Unity 3D 與 WPF/Sliverlight 不同,它沒有提供類似的 Data Binding,也沒有像 XAML 一樣的視圖文法,那麼怎樣才能在 Unity 3D 中去實作 MVVM 呢?

在 ASP.NET WebForm 時代,那時還沒有 ASP.Net MVC 。我們為了讓 UI 表現層分離,常常會使用 MVP 設計模式,以下是我在幾年前畫的一張老圖:

MVP 設計模式核心就是,通過定義一個 View,将 UI 抽象出來,它不必關心資料的具體來源,也不必關心點選按鈕之後業務邏輯的實作,它隻關注 UI 互動。這就是典型的分離關注點。

其實這就是我今天想講的主題,既然 Unity 3D 沒有提供資料綁定,那麼我們也可以參考之前 MVP 的設計理念:

将 UI 抽象成獨立的一個個 View,将面向 Component 開發轉換為面向 View 開發,每一個 View 都有獨立的 ViewModel 進行管理,如下所示:

由于 Unity 3D 沒有 XAML,也沒有 Data Binding 技術,故隻能在抽象出來的 View 中去實作類似于 WPF 的 Data Binding,Converter,Command 等。

值得注意的是,MVP 設計模式中資料的綁定是通過将具體的 View 執行個體傳遞到 Presenter 中完成的,而 MVVM 是以資料改變引發的事件中完成資料更新的。

再回顧一下 WPF 中 ViewModel 的寫法。 ViewModel 提供了 View 需要的資料,并且 ViewModel 實作 INotifyPropertyChanged 接口 ,當資料更改時,觸發了 PropertyChanged 事件,由于控件也監聽了此事件,在事件的響應函數裡實作資料的更新。

了解了之後,我們要考慮怎樣在 Unity 3D 中去實作它。假設我們需要完成如下的一個功能,并且是使用 MVVM 設計思想實作:

首先,我們要定義一個 View,這個 View 是對 UI 元素的一個抽象,到底要抽象哪些 UI 元素呢?就這個例子而言,InputField,Label,Slider,Toggle,Button 是需要被抽象出來的。

可以看到,這是一個很簡單的 View。接着我們需要定義一個專門用來管理 View 的 ViewModel,它以屬性的形式提供資料,以方法的形式提供行為。

值得注意的是,ViewModel 中的屬性不是特殊的屬性,它必須具備當資料更改時通知訂閱者這個功能,怎麼通知訂閱者?當然是事件,故我把此屬性稱為 BindableProperty 屬性。

接着,我們再定義一個 ViewModel,它為 View 提供了資料和行為:

有了 View 與 ViewModel 之後,我們需要考慮:

怎樣為 View 指定一個 ViewModel

當 ViewModel 屬性值改變時,怎樣訂閱觸發的 OnValueChanged 事件,進而達到 View 的資料更新

基于以上兩點,我們可以定義一個通用的 View,将它命名為 UnityGuiView :

上述代碼中,提供一個 BindingContext 上下文屬性,類似于 WPF 中的 DataContext。 BindingContext 屬性我們不能将它視為一個簡單的屬性 ,它是上述定義過的 BindableProperty 類型屬性。那麼當為一個 View 的 BindingContext 指定 ViewModel 執行個體時,初始化時,勢必會觸發 OnValueChanged 事件。

在響應函數 OnBindingContextChanged 中 ,我們可以在此對 ViewModel 中事件進行監聽,進而達到資料的更新。當然這是一個虛方法,你需要在子類 View 中 Override。

是以修改定義過的 SetupView,繼承自 UnityGuiView:

由于子類 Override 了 OnBindingContextChanged 方法,故它會對 ViewModel 的屬性值改變事件進行監聽,當觸發時,将最新的資料同步到 UI 中。

同理,考慮到雙向綁定,你也可以在 View 中定義一個 OnTextBoxValueChanged 響應函數,當文本框中的資料改變時,在響應函數中就資料同步到 ViewModel 中。在這我就不累述了。

最後,在 Unity 3D 中将 SetupView 附加到 相應的 GameObject上:

最後在錄影機上加一段腳本,很簡單,傳入 SetupView 對象并為其綁定 ViewModel:

這是一個非常簡單的 MVVM 架構,也證明了在 Unity 3D 中實作 MVVM 設計模式的可能性。
Unity應用架構設計(1)—— MVVM 模式的設計和實施(Part 1)

本文轉自木宛城主部落格園部落格,原文連結:http://www.cnblogs.com/OceanEyes/p/unity3d_framework_designing_get_started_with_mvvm_part1.html,如需轉載請自行聯系原作者

繼續閱讀