RIAWAVE – 一個輕量化的Flex 2 應用程式開發手法(4)
*riawave關鍵部份說明
◇Views – 主要的使用者介面
這支程式的設計手法是以 “component-based design” 為核心,畫面上所有的UI元件都合理的區分為不同的 logical unit,也就是 mxml component,或一般所稱的 views,通常它的命名傳統為 FormXXXX。
透過合理的 component 建構可享受的好處在於『彈性』,它又可以從下列幾個角度來看:
-相依性低:
form 彼此之間的相依性極低,彼此的交談,以及 form 與 dao間的交談都是透過事件廣播來達成,因此彼此的相依性降到最低,將來任何一個 form 變動(例如更改api或功能改變)都不會影響到系統中其它元件的運作,甚至也可以動態抽換其中的元件。
-版面變更容易:
由於 UI 版面配置不是採 water-fall 式的由上而下鋪陳在同一個mxml頁面裏,而是依功能性區隔在不同的mxml component(也就是 form)內,因此任何時候要變更版面設計,只要將 form 移往不同位置即可,例如原本 FormDetail是放在畫面的右邊,如果客戶要求將其改放在 pop-up window內,只要將 FormDetail 移到另一個 Panel 元件裏即完成。
-複用性高:
由於元件是按照其功能與屬性合理的切割,因此部份form 將來可重複使用,例如 Login, Register, ForgetPassword等,幾乎是每支web application都會需要的元件,這些部份只要製作一次,將來就可以將mxml直接複製到新project內使用。
◇VO – 傳遞資料時使用的物件
Value Object (又稱 Data Transfer Object, DTO)主要是用來在client 與 server間傳遞資料使用,透過 strict typing 可避免一般使用 plain object 時的問題,例如資料態錯誤等,同時也方便 client 與 server間自動mapping 物件,此點對於後台使用 java 的人更為重要。
目前大部份 remoting gateway 都提供自動mapping的服務,因此可能的情況下應該儘量使用 vo。
在 Riawave中,form<-> form 以及 form<->dao間的資料交換,一律都是以 vo 為基礎,同時存在 ModelLocator 中的物件與Array等,也都是vo。
◇DAO – 負責存取app server交換資料
Data Access Object 是專門用來存取 server端的物件,例如透過 remoting gateway 來回傳送資料到app server,並接收將server的回傳值。
這一層的用意是將client內所有需要存取server的動作都隔離開來,程式內所有的form 只操作 dao 這個物件,至於這個dao內部是透過何種方式與 server 溝通則沒有必要知道。
完全隔離的好處是將來如果要更換連線方式,例如原本使用 flash remoting, 但後來要換成 web service,只要在 dao內部修改即可,對程式中的其它form而言,只要 dao 的 public API沒變,則一切即可繼續運作無誤。
如果搭配 Spring Dependency Injection 的概念與 Class Factory 的手法,可在 runtime 透過 config xml 動態決定要使用何種方式與server連接,例如 http service, xml, web service 或 flash remoting。
Note: dao 在標準的 Java Pattern 中只是一個很小的部份,一般上一層還會有 Service Object,但此處為簡化範例,因此直接取用 DAO 名稱來代表這個概念。
◇ModelLocator – 廣播、儲存與singleton
ModelLocator主要的任務有三個:
一、 廣播中心:所有view、dao與其它物件要廣播時,統一都透過它的 dispatchEvent()執行;而所有需要知道(觀察)這個事件的物件,也統一透過它的 addEventListeners()來偵聽。
二、 儲存中心:所有程式執行階段要共用的變數,例如目前登入的使用者(user object)或系統設定值(system preference)甚至是datagrid裏目前選取的項目(selected item)都可以存在這裏;並且,這個class通常會設定為 [Bindable],讓其它物件可透過 data binding 直接存取資料,例如 {ModelLocator.getInstance().user.name}。
三、 Singleton: 由於 ModelLocator裏的資料是整支程式所共用,因此它必需是 Singleton,如此所有的物件才能存取同一個 reference。
以實務上應用來說,最常見的用途就是:
-當一個form要跟另一個form溝通時(例如 FormA 要傳一個值給 FormB),標準的做法是
FormA內:
ModelLocator.getInstance().dispatchEvent( new CustomEvent(“MyEvent”, dataObject));
FormB內:
ModelLocator.getInstance().addEventListener(“MyEvent”, onMyEvent);
Function onMyEvent( evt:CusomEvent ){
//handle the event
}
這樣做的好處有:
1、FormA 不會知道有 FormB 的存在,它只管拋出一個事件,內含要傳遞的資料
2、需要知道 MyEvent 的物件,自然會透過統一的廣播系統(ModelLocator)去偵聽這個事件然後處理,因此一個事件可以有許多個偵聽者,方便系統內不同部份協同處理
3、每個物件的封裝性不會被迫壞,不用像 ViewHelper一般必需要曝露元件內部的mehtod讓外界知道與操作,如此一來將來要重構元件或更改功能皆很方便,不用擔心會損壞其它部份。
而另一個讓 FormA 與 FormB 溝通的做法則是透過 binding,例子如下:
FormA:
例如在 FormA 內的 DataGrid 選取了一個物件,可以這樣寫
<mx:DataGrid id=”dg” change=”ModelLocator.getInstance().user = dg.selectedItem” />
也就是將目前 datagrid 選取的 item 存入 ModelLocator中。
FormB:
假設在 FormB中有一個 label 要顯示目前選取的user,可以這樣寫
<mx:Label text=”{ModelLocator.getInstance().user.name}” />
也就是使用 binding 將label 的 text property bind到 ModelLocator 的 user物件上。
這樣的做法跟第一種「事件廣播」法其實是一異曲同功,兩個form彼此之間是完全隔離而沒有相依性,只透過中間第三者(ModelLocator)轉手處理訊息,這也是目前 Cairngorm 2 裏面推崇的做法。
◇CustomEvent – 自製 Event 物件
Flex 2 / AS3 最大的特色之一就是全新的 Event Model,事件有特良好的循還廣播系統(dispatching and bubbling),因此我們應該善用這個事件體系做為物件間彼此溝通的管道。
在flexsample內,我們使用了一個 CustomEvent物件,它的特色如下:
1、每個 custom event 都必需繼承自 flash.net.Event 或它的 sub-class
2、custom event 內應該使用 public static const (常數) 來標示事件的名稱,標準做法如下
public static const ADD_CONTACT:String = “addContact”
其中常數的名稱為全大寫(all capitals),而後面的字串則採 camel case,第一個字母小寫,第二個之後大寫,這是 Adobe工程師撰寫 flex framework 時採用的標準 coding standard,也建議大家採用。
3、事件內有 data 與 msg 兩個 property,並且event 本身是 sealed class
Data 是用來放置要隨者 event 而廣播出去的資料,例如 vo 或 resultset
Msg 是放額外的資訊,通常是字串或 status message,這個可有可無


1 Comment Add your own
1. cmanwalking&hellip | September 14th, 2006 at 7:29 pm
看了前辈的教程,深入浅出,明白了很多。谢谢!不知道还有没有了?
Trackback this post | Subscribe to the comments via RSS Feed