PureMVC, 快樂玩Part1
最近除了熱血的工作, 熱血的研究Progression, 當然還有熱血的PureMVC
好吧, 我承認這東西有一定的難度, 但上手後, 真的還滿方便的。
PureMVC是一種程式語言的框架, 不限於 AS3 , 官網有很多的版本可以任君選擇。
主要有三個概念
Model, Proxy
負責將數值變數存起來, 當數值被更改時, 就發送通知, 然後就什麼事也不做了。
View,Mediator
一個Mediator就對映一個View(視覺元件), 當View做了某件事情後, 發送通知。
Controller,Command
當 Mediator 被通知到後, 就執行事件做作好的Command
有了簡單概念後, 來開始試寫看看。
先下載 PureMVC AS3 standard 2.0.4版本
在這兒我們寫了一個小型的相本, 由 xml 管理, 畫面上有左、右鍵,二個動態文字
和一個要載入圖片用的Sprite。
奶小茶的習慣是先從Proxy來開始寫, 因為載入資料是最先要做的事情。
ListProxy.as
有了Proxy後,下一步來寫View跟Mediator
在這兒我們就只有一個主場景, 所以就準備一個ApplicationMediator.as
Mediator的工作就是觀查視覺元件的一切, 偵聽他的事件
更改他的數值, 就是他的保母啦。
ApplicationFacade, PureMVC 的總代理, 在這奶小茶使用的是 Standard版
所以只會有一個Facade, 如果要多個應用程式, 多個Facade的話,可以選用 MultiCore版本。
所有的 Proxies , Mediators 跟 Commands 註冊
他的程式碼很少, 都是固定的寫法。
啟動用的Command
StartupCommand.as
再來就是整個Clinet的主程式。
完成啦, 搞的大家都很不熟, 這就是PureMVC的精神呀
下次在專案上實作看看。
SourceCodeDownload
最近除了熱血的工作, 熱血的研究Progression, 當然還有熱血的PureMVC
好吧, 我承認這東西有一定的難度, 但上手後, 真的還滿方便的。
PureMVC是一種程式語言的框架, 不限於 AS3 , 官網有很多的版本可以任君選擇。
主要有三個概念
Model, Proxy
負責將數值變數存起來, 當數值被更改時, 就發送通知, 然後就什麼事也不做了。
View,Mediator
一個Mediator就對映一個View(視覺元件), 當View做了某件事情後, 發送通知。
Controller,Command
當 Mediator 被通知到後, 就執行事件做作好的Command
有了簡單概念後, 來開始試寫看看。
先下載 PureMVC AS3 standard 2.0.4版本
在這兒我們寫了一個小型的相本, 由 xml 管理, 畫面上有左、右鍵,二個動態文字
和一個要載入圖片用的Sprite。
奶小茶的習慣是先從Proxy來開始寫, 因為載入資料是最先要做的事情。
ListProxy.as
package milkmidi.puremvc.model { import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; import milkmidi.puremvc.model.vo.ListVO; import org.puremvc.as3.interfaces.IProxy; import org.puremvc.as3.patterns.proxy.Proxy; public class ListProxy extends Proxy implements IProxy { public static const NAME :String = "ListProxy"; //當 xml 載入完成後, 會發送notification public static const DATA_LOAD_COMPLETE :String = 'dataLoadComplete'; //當 xml 索引值改變時 public static const MODEL_CHANGE :String = 'modelChange'; //當 ListProxy 被設定新值時 public static const SET_CURRENT_INDEX :String = 'setCurrentIndex'; private var _urlLdr :URLLoader = new URLLoader(); private var _xml :XML; private var _currentIndex :uint = 0; public function ListProxy(data:Object = null) { super(NAME, data); _urlLdr.addEventListener(Event.COMPLETE , completeHandler); _urlLdr.load(new URLRequest('xml_data.xml')); //載入 xml 。 } private function completeHandler(e:Event):void { _xml = XML(e.currentTarget.data); //載入完成後,將得到的 xml 設定到 data裡。 setData( _xml ); sendNotification(DATA_LOAD_COMPLETE , data); //記得要發通知喔。 } public function setCurrentIndex(pIndex:uint):void { _currentIndex = pIndex; //設定索引值 if (_currentIndex < 0) _currentIndex = 0; else if (_currentIndex >= length - 1) _currentIndex = length - 1; //判斷有沒有爆掉。 var _vo:ListVO = new ListVO(); _vo.img = currentImgURL; _vo.title = currentTitle; _vo.page = currentPage; //將新的數值發送出去。 sendNotification(MODEL_CHANGE , _vo); } public function get length():uint { return _xml.item.length(); } public function get currentImgURL():String { return _xml.item[currentIndex].img; } public function get currentTitle():String { return _xml.item[currentIndex].title; } public function get currentPage():String { return (_currentIndex + 1) +'/' + length; } public function get currentIndex():uint { return _currentIndex; } } } //在這兒也準備一個VO(ValueObject), 方便給大家使用。 ListVO.as package milkmidi.puremvc.model.vo { public class ListVO { public var title:String = ''; public var img :String = ''; public var page :String = ''; public function ListVO() { } } }
有了Proxy後,下一步來寫View跟Mediator
在這兒我們就只有一個主場景, 所以就準備一個ApplicationMediator.as
Mediator的工作就是觀查視覺元件的一切, 偵聽他的事件
更改他的數值, 就是他的保母啦。
package milkmidi.puremvc.view { import flash.events.Event; import milkmidi.puremvc.model.ListProxy; import milkmidi.puremvc.model.vo.ListVO; import org.puremvc.as3.interfaces.IMediator; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.mediator.Mediator; import milkmidi.puremvc.view.*; public class ApplicationMediator extends Mediator implements IMediator { // Cannonical name of the Mediator public static const NAME:String = "ApplicationMediator"; public function ApplicationMediator(viewComponent:Object) { super(NAME, viewComponent); //偵聽主場景上的事件。 container.addEventListener('nextItem' , nextItemHandler); container.addEventListener('prevItem' , prevItemHandler); } private function prevItemHandler(e:Event):void { sendNotification( ListProxy.SET_CURRENT_INDEX , -1 ); //發送通知。 } private function nextItemHandler(e:Event):void { sendNotification( ListProxy.SET_CURRENT_INDEX , 1 ); //發送通知。 } override public function getMediatorName():String { return ApplicationMediator.NAME; } override public function listNotificationInterests():Array { return [ ListProxy.DATA_LOAD_COMPLETE, ListProxy.MODEL_CHANGE ]; //我只關心這些通知, 其他沒寫的就通通不管。 } override public function handleNotification(note:INotification):void { trace(facade.retrieveProxy( ListProxy.NAME)); //得到發送事件的 ListProxy 實體。 trace(note.getBody()) //得到發送通知時, 一起帶過來的數值 switch (note.getName()) { case ListProxy.DATA_LOAD_COMPLETE: sendNotification( ListProxy.SET_CURRENT_INDEX , 0 ); break; case ListProxy.MODEL_CHANGE: var _listVO:ListVO = note.getBody() as ListVO; container.title_txt.text = _listVO.title + ''; container.numbers_txt.text = _listVO.page; break; default: break; } } private function get container():Main { return viewComponent as Main; //轉型用, 給自己看的。 } } } //另一個ImageContainerMediator.as ,是觀查場景上的載入圖片用的Sprite, 寫法差不多,就不多介紹了。
ApplicationFacade, PureMVC 的總代理, 在這奶小茶使用的是 Standard版
所以只會有一個Facade, 如果要多個應用程式, 多個Facade的話,可以選用 MultiCore版本。
所有的 Proxies , Mediators 跟 Commands 註冊
他的程式碼很少, 都是固定的寫法。
package milkmidi.puremvc { import flash.display.Stage; import org.puremvc.as3.interfaces.IFacade; import org.puremvc.as3.patterns.facade.Facade; import milkmidi.puremvc.model.*; import milkmidi.puremvc.view.*; import milkmidi.puremvc.controller.*; public class ApplicationFacade extends Facade implements IFacade { // Notification name constants public static const STARTUP:String = "startup"; public static function getInstance():ApplicationFacade { if (instance == null) instance = new ApplicationFacade(); return instance as ApplicationFacade; } // Register commands with the controller override protected function initializeController():void { super.initializeController(); registerCommand(STARTUP, StartupCommand); } public function startup( pApp:Main ) : void { sendNotification( STARTUP, pApp ); //這兒是用來啟動整個 PureMVC用的 } } }
啟動用的Command
StartupCommand.as
package milkmidi.puremvc.controller { import milkmidi.puremvc.model.ListProxy; import milkmidi.puremvc.view.ApplicationMediator; import milkmidi.puremvc.view.ImageContainerMediator; 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 { var _main:Main = notification.getBody() as Main; facade.registerMediator( new ApplicationMediator( _main)); //注冊 Mediator facade.registerMediator( new ImageContainerMediator( _main.container_mc)); //注冊 Mediator, 在這兒是用來載入外圖品片的容器。 facade.registerProxy( new ListProxy()); //注冊 Proxy。 facade.registerCommand( ListProxy.SET_CURRENT_INDEX , ModelChangeCommand); //注冊 Command } } } //當要更改 ListProxy裡數值用的Command package milkmidi.puremvc.controller { import milkmidi.puremvc.model.ListProxy; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; import org.puremvc.as3.patterns.observer.Notification; public class ModelChangeCommand extends SimpleCommand { override public function execute(note:INotification):void { var _listProxy :ListProxy = facade.retrieveProxy( ListProxy.NAME ) as ListProxy; var _data :int = int(note.getBody()); _listProxy.setCurrentIndex(_listProxy.currentIndex + _data); } } }
再來就是整個Clinet的主程式。
package { import flash.display.MovieClip; import flash.display.SimpleButton; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.text.TextField; import milkmidi.puremvc.ApplicationFacade; public class Main extends Sprite { //場景上的元件 public var right_btn :SimpleButton; public var left_btn :SimpleButton; public var numbers_txt :TextField; public var title_txt :TextField; public var container_mc :MovieClip; public function Main() { right_btn.addEventListener(MouseEvent.CLICK , clickHandler); left_btn.addEventListener(MouseEvent.CLICK , clickHandler); ApplicationFacade.getInstance().startup( this ); //啟動PureMVC。 } private function clickHandler(e:MouseEvent):void { //左、右鍵只管發送事件, 就沒啦。 if (e.currentTarget == left_btn) dispatchEvent(new Event('prevItem')); else dispatchEvent(new Event('nextItem')); } } }
完成啦, 搞的大家都很不熟, 這就是PureMVC的精神呀
下次在專案上實作看看。
SourceCodeDownload
留言
相對程式碼也會比較多
如果只是小型的應用程式
不一定要用pureMVC
不果這東西這麼紅, 一定有他的道理在
到Google打,第一筆就是他的網站
在規劃程式的時候`,你會先在紙上做UML圖的規劃嗎?
通常都以功能面來規劃