參考資料 : pureMVC 官方網站
也許對於"純"程式設計師來說 pureMVC 才是比較正統的 MVC design pattern 的作法...跟它相處了兩天還是沒辦法對它產生愛啊... 也許它的可攜性比較高...但是我實在看不到它可愛在哪裡...也許它太正統了;也許是因為它都不使用 Flex framework吧...(可能需要慢慢體會...)
先了解它的主要架構就是一對一對的:
• Model vs. Proxy
• View vs. Mediator
• Controller vs. Command
以下是同上篇 [Flex] Cairngorm 練習筆記 一樣的工作改為 pureMVC 寫法
Menu tree:
list.xml :
0. ListVO
1. 從 ListProxy 開始寫
pureMVC 的 Proxy 主要的工作大概就是:
2. ListMediator:對應 List Component 在主要的 mxml 上
Mediator 主要的工作有:
3. ApplicationFacade:MVC 的總代理,它當然是只有一個
所有的 Proxies , Mediators 跟 Commands 註冊、取用與毀滅都在這邊,不過為了"儘量"跟別人沒關係,它這邊除了 Commond 的註冊外,其餘都是寫在 StartupCommand 內。以下幾乎是 ApplocationFacade 的標準寫法。
反正就是先註冊了一個 StartupCommand 然後馬上 Notification 它~~
4. StartupCommand
該初始化的都在這邊完成~~
5. TestPureMVC.mxml
到目前的理解,pureMVC 事件傳遞機制是採用 Observer vs. Notification。如果有註冊成組的 Command 與 Notification ,Notification 被發送時也會執行 Command,然後 viewComponent 採用 as3 的 Event 機制發送 Event 給 Mediator 監聽...反正就是多用 Notification & Command吧...
to be continue....?
也許對於"純"程式設計師來說 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....?
感謝Erin大大的教學~
ReplyDelete看來對於龐大的項目,還是要先找個比較適合的pattern歸宿啊
個人感覺Flex framework的UI部分太臃腫了,而且又難Hack,那些API足以讓我抓狂一天
還是比較喜歡“純”AS project,light-weight的東西,不知哪里有更優的UI呢
我倒蠻喜歡 Flex 的 mxml 編寫方式...XD 好適合懶人啊...
ReplyDeletemxml 不錯!!!
ReplyDelete其實自訂的方式還滿容易的
(感覺上...
pure有點難啃...
多啃幾次
registerCommand的時機
ReplyDelete只能在ApplicationFacade裡面嗎?
如果有非常多的Controller設定的數量...
好像會滿可觀的
registerCommand 並不是一定得在 ApplicationFacade 裡喔!
ReplyDelete很好入門的一篇教學~讚!!
ReplyDelete