Skip to main content

[Flex] pureMVC Standard 練習筆記

參考資料 : pureMVC 官方網站

也許對於"純"程式設計師來說 pureMVC 才是比較正統的 MVC design pattern 的作法...跟它相處了兩天還是沒辦法對它產生愛啊... 也許它的可攜性比較高...但是我實在看不到它可愛在哪裡...也許它太正統了;也許是因為它都不使用 Flex framework吧...(可能需要慢慢體會...)

先了解它的主要架構就是一對一對的:

• Model vs. Proxy
• View vs. Mediator
• Controller vs. Command

以下是同上篇 [Flex] Cairngorm 練習筆記 一樣的工作改為 pureMVC 寫法
Menu tree:


list.xml :

<?xml version="1.0" encoding="utf-8"?>
<data>
<list name="AAAA" data="0"/>
<list name="BBBB" data="1"/>
<list name="CCCC" data="2"/>
<list name="DDDD" data="3"/>
</data>


0. ListVO
package com.mvc.model.vo
{
public class listVO
{
public function listVO(label:String, data:String){
this.label = label;
this.data = data;
}
public var label:String;
public var data:String;
}
}


1. 從 ListProxy 開始寫
pureMVC 的 Proxy 主要的工作大概就是:
  • 匯集對應 Models 提供方法、屬性給別人使用 ( 建議:給自己或 Command 修改就好 )

  • 要努力跟 Mediator 絕交,不要認識最好

  • 封裝區域邏輯 ( 反正就是弄好資料才給別人 )

  • 只發不收 Notification

package com.mvc.model
{
import mx.rpc.IResponder;
import mx.rpc.http.HTTPService;
import mx.collections.ArrayCollection;
import com.mvc.model.vo.listVO;

import org.puremvc.as3.patterns.proxy.Proxy;

public class ListProxy extends Proxy implements IResponder
{
public static const NAME:String = "listProxy";
public static const LIST_CHANGED:String ="list_changed";

public function ListProxy()
{
super(NAME, new ArrayCollection);
update();
}
public function update():void{
var httpService:HTTPService = new HTTPService();
httpService.url="data/list.xml";
httpService.resultFormat = "e4x";
var call:Object = httpService.send();
call.addResponder(this);
}
//隱藏的 getter 給自己看的,順便轉換資料型態
private function get list() : ArrayCollection {
return data as ArrayCollection;
}
/**
* Implemented mx.rpc.IResponder
* 外面的別用這兩個方法
*/
public function result( event:Object ):void{
var xml:XML = XML(event.result);
var list:ArrayCollection = new ArrayCollection;
for each (var subxml:XML in xml.list){
list.addItem( new listVO ( subxml.@name, subxml.@data));
}
setData(list);
//改完就要發 Notification
sendNotification( LIST_CHANGED, data );
}
public function fault( obj:Object ):void{
trace("XML 載入錯誤");
}
}
}


2. ListMediator:對應 List Component 在主要的 mxml 上
Mediator 主要的工作有:
  • 監聽並反應 viewComponent 發送的 Events

  • 可收發與處理 Notifications

  • 避免直接修改 Proxy ,要嘛就是用 Command

  • 其他?...( 跟它還不夠熟 )

package com.mvc.view
{
import com.mvc.model.ListProxy;

import mx.collections.ArrayCollection;
import mx.controls.List;

import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;

public class ListMediator extends Mediator
{
public function ListMediator(mediatorName:String=null, viewComponent:Object=null)
{
super(mediatorName, viewComponent);
}
override public function listNotificationInterests():Array
{
//要處理啥訊息都在這邊列好
return [
ListProxy.LIST_CHANGED
];
}

override public function handleNotification(notification:INotification):void
{
//上面有列這邊才收的到喔!
switch(notification.getName()){
case ListProxy.LIST_CHANGED:
list.dataProvider = notification.getBody() as ArrayCollection;
}
}
//給自己看的,重點還是轉換物件型態
private function get list():List {
return viewComponent as List;
}

}
}


3. ApplicationFacade:MVC 的總代理,它當然是只有一個
所有的 Proxies , Mediators 跟 Commands 註冊、取用與毀滅都在這邊,不過為了"儘量"跟別人沒關係,它這邊除了 Commond 的註冊外,其餘都是寫在 StartupCommand 內。以下幾乎是 ApplocationFacade 的標準寫法。

package com.mvc
{
import org.puremvc.as3.patterns.facade.Facade;
import org.puremvc.as3.interfaces.IFacade;
import com.mvc.control.StartupCommand;

public class ApplicationFacade extends Facade implements IFacade
{
public static const STARTUP:String = "startup";
public function ApplicationFacade()
{
super();
}
public static function getInstance() : ApplicationFacade
{
if ( instance == null ) instance = new ApplicationFacade( );
return instance as ApplicationFacade;
}

override protected function initializeController( ) : void
{
super.initializeController();
registerCommand( STARTUP , StartupCommand );
}

public function startup( app:TestPureMVC ) : void
{
sendNotification( STARTUP, app );
}
}
}

反正就是先註冊了一個 StartupCommand 然後馬上 Notification 它~~

4. StartupCommand
該初始化的都在這邊完成~~
package com.mvc.control
{
import com.mvc.model.ListProxy;
import com.mvc.view.ListMediator;

import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.command.SimpleCommand;

public class StartupCommand extends SimpleCommand
{
public function StartupCommand()
{
super();
}
override public function execute(notification:INotification):void{
//這邊只控制畫面上的list component...- - 它的 id = list
var list:Object = notification.getBody().list;
facade.registerMediator( new ListMediator(null, list) );
facade.registerProxy( new ListProxy());
}
}
}


5. TestPureMVC.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="220" height="200" layout="absolute"
applicationComplete="facade.startup( this )" >
<mx:Script>
<![CDATA[
import com.mvc.ApplicationFacade;
private var facade:ApplicationFacade = ApplicationFacade.getInstance();
]]>
</mx:Script>
<!-- ListMediator 的控制對象-->
<mx:List id="list" />
</mx:Application>


到目前的理解,pureMVC 事件傳遞機制是採用 Observer vs. Notification。如果有註冊成組的 Command 與 Notification ,Notification 被發送時也會執行 Command,然後 viewComponent 採用 as3 的 Event 機制發送 Event 給 Mediator 監聽...反正就是多用 Notification & Command吧...

to be continue....?

Comments

  1. 感謝Erin大大的教學~

    看來對於龐大的項目,還是要先找個比較適合的pattern歸宿啊
    個人感覺Flex framework的UI部分太臃腫了,而且又難Hack,那些API足以讓我抓狂一天
    還是比較喜歡“純”AS project,light-weight的東西,不知哪里有更優的UI呢

    ReplyDelete
  2. 我倒蠻喜歡 Flex 的 mxml 編寫方式...XD 好適合懶人啊...

    ReplyDelete
  3. mxml 不錯!!!
    其實自訂的方式還滿容易的
    (感覺上...

    pure有點難啃...
    多啃幾次

    ReplyDelete
  4. registerCommand的時機
    只能在ApplicationFacade裡面嗎?

    如果有非常多的Controller設定的數量...
    好像會滿可觀的

    ReplyDelete
  5. registerCommand 並不是一定得在 ApplicationFacade 裡喔!

    ReplyDelete
  6. 很好入門的一篇教學~讚!!

    ReplyDelete

Post a Comment

Popular posts from this blog

[Unity] erinylin.lazylib - Cookie for PlayerPrefs

有鑑於 PlayerPrefs 測試與版本更新問題,將大家都愛用的 PreviewLabs.PlayerPrefs 打包起來,製作重點還是以懶人為主,基本上 PlayerPrefs 資料更新與數量並不可能會有強烈衝擊效能的狀況產生,所以為了方便開發,就弄了一個視覺化工具,方便除錯用。

雖然 PreviewLabs.PlayerPrefs 作者都宣告放棄他們的版權,不過為了尊重程式,僅僅加入了兩個公用函式,其他並無更改。

內有:
Cookie ManagerCookie 用 DataObject 混合編輯 ScriptableObject執行階段除錯視窗工具當然還是有懶人常數檔案輸出資料版本控制,方便更新版後儲存資料更新功能其實很多,有興趣的請自行到 Github 下載並參考範例吧!

[AIR] JoSiResize - Mobile 開發小工具

JoSiResizev0.6.0,Adobe AIR 3 runtime之前開發 tool app 的時候並沒有很深刻的體認到圖片素材的 resize 是一個很麻煩的事情...畢竟圖片使用量並不大,等到開發遊戲類的 app 才發現光處理不同螢幕尺寸的圖片素材是一個相當折磨人的工作。
因此 JoSiResize app 誕生了~~~原理是採用最小 scale 長寬比例不變的方式進行放大縮小。使用方法非常簡單,設定好變更的尺寸,接下來,將需要處理的圖片檔案全選直接拖曳到視窗內,畫面即會跳出預備儲存的檔案夾選擇畫面,確認後即開始轉檔。

[Mac app] 開啟 Mac OSX 中自帶的 Color Picker 並加上 HexColorPicker 功能

參考出處:Mac — Adding Hex Color Picker to Color Picker

Mac app store 上有很多 Color Picker app,差不多 98% 都是需要付費,而這個小工具恰恰是開發中不可缺少一個東西。其實 Mac OSX 中就有自帶一個 ColorPicker,秉持著 DIY 的精神,用幾個小步驟就可以組合出顯示 Hex 色碼的 ColorPicker.app。

Mac 系統需求:10.4 and up