<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-31  評(píng)論-257  文章-0  trackbacks-0
          做Flex做久了做大了,就會(huì)覺(jué)得之前寫(xiě)的的Flex代碼開(kāi)始有點(diǎn)亂,哪怕你寫(xiě)的規(guī)范了,但總覺(jué)得結(jié)構(gòu)松散,維護(hù)不方便,相信很多人剛開(kāi)始做Flex的時(shí)候,都是想到什么功能,就寫(xiě)什么功能,或者有些好點(diǎn)的,就先畫(huà)了個(gè)大體的流程圖之類的,因?yàn)楝F(xiàn)在Flex普及得還不夠,很多人做Flex也是試探階段,不敢用作商業(yè)項(xiàng)目或其它大項(xiàng)目,只會(huì)用來(lái)試水技術(shù)層面的,所以都是做些小應(yīng)用的多,就會(huì)忽略了設(shè)計(jì)一個(gè)比較好的框架來(lái)開(kāi)發(fā)。所以Flex的開(kāi)發(fā)框架就應(yīng)運(yùn)而生了。目前,好的Flex開(kāi)發(fā)框架還不多,官方有個(gè)Cairngorm的框架,可能有些人會(huì)說(shuō)這個(gè)框架有點(diǎn)復(fù)雜,其實(shí)不然,對(duì)比起Ruby的Rails,Java的Struts,Spring之類的開(kāi)發(fā)框架,就顯得簡(jiǎn)單得多了。只要清楚了解要MVC的概念,就會(huì)對(duì)這些框架并不陌生,但是今天的主角不是Cairngorm,而是另一個(gè)Flex框架 PureMVC,如果說(shuō)Cairngorm復(fù)雜的話,那么PureMVC就顯得簡(jiǎn)單多了,PureMVC比較輕盈,核心也只有十來(lái)個(gè)類,是一個(gè)輕量級(jí)的Flex框架,但PureMVC的通用性還是比較廣的,有PHP的,有Java的有Python的。可能直接說(shuō)框架的使用會(huì)比較抽象,那么就由一個(gè)實(shí)例來(lái)開(kāi)始講解吧,就用一個(gè)PureMVC做的一個(gè)MP3播放器。



    先來(lái)看看PureMVC的結(jié)構(gòu)圖:



          在圖中,F(xiàn)acade,Model,View,Controller都是PureMVC的四個(gè)核心類,都是單例模式的,用戶無(wú)需操作那Model,View,Controller類,而用戶只需要操作Facade就夠了,F(xiàn)acade類用來(lái)管理其它的三個(gè)單例類,顧名思義,那三個(gè)類都是分別對(duì)應(yīng) MVC 模式的那三個(gè)元素,F(xiàn)acade也是個(gè)單例,它負(fù)責(zé)創(chuàng)建,激活,調(diào)用其它的三個(gè)類,管理MVC各屋的生命周期。
          而我們看看Model類,又細(xì)分了一個(gè)Proxy類出來(lái),我們稱其為代理吧,就是對(duì)數(shù)據(jù)模型的一個(gè)代理,負(fù)責(zé)訪問(wèn)我們的數(shù)據(jù)對(duì)象(Data Object)也就是Cairngorm中的ValueObject,其實(shí)都是同一個(gè)概念。而類結(jié)構(gòu)上,對(duì)數(shù)據(jù)操作的代理Proxy類就只有一個(gè),但可以從我們的應(yīng)用上又分為L(zhǎng)ocal Proxy,Remote Proxy,其實(shí)都只是Proxy ,只是根據(jù)用戶的應(yīng)用的不同,在Proxy里面實(shí)現(xiàn)不同的功能而已,比如如果你操作本地?cái)?shù)據(jù)(內(nèi)存中的數(shù)據(jù),并非本地操作系統(tǒng)的文件),你可以寫(xiě)一些VO的getter/setter直接操作數(shù)據(jù),而如果是Remote的數(shù)據(jù)的話,你可以在Proxy類里定義一些HttpService,URLLoader,WebService等等的訪問(wèn)遠(yuǎn)程數(shù)據(jù)的API,之后將獲取到的遠(yuǎn)程數(shù)據(jù)放在VO中。
          在Controller類里分出一個(gè)叫Command的類來(lái),直接翻譯的話,就是“命令”類,通常這些類都是用來(lái)處理一些業(yè)務(wù)流程,某些算法操作等等的操作。比如現(xiàn)在用戶單擊了“獲取數(shù)據(jù)”的按鈕,程序?qū)腜roxy類里訪問(wèn)服務(wù)器,服務(wù)器返回?cái)?shù)據(jù)之后,那些都是程序看得懂的數(shù)據(jù),比如是XML,而如果數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,你不可能直接將數(shù)據(jù)顯示給用戶看吧?那就將解析這些數(shù)據(jù)的工作交給Command來(lái)做,比如寫(xiě)一個(gè)ParseCommand的類,將獲得的XML數(shù)據(jù)傳遞給該Command,在Command里進(jìn)行數(shù)據(jù)的過(guò)濾,排列,整理等等的功能。再將組積好后數(shù)據(jù)交給Mediator來(lái)進(jìn)行顯示,而Mediator,就是下面我們要說(shuō)的。
          在View類里分出一個(gè)Mediator的類,該類是用來(lái)對(duì)ViewComponent操作的,我們暫且叫它“中介類”吧,為什么叫“中介”呢?其實(shí)就是用戶界面(UI)與程序結(jié)構(gòu)邏輯之間的中介,因?yàn)橛脩粼诮缑嫔系牟僮鳎热鏐utton的Click事件不是直接反映到Command或者Proxy類上的,而是反映給Mediator類,在Mediator里作一些簡(jiǎn)單處理,比如驗(yàn)證合法性,觸發(fā)其它ViewComponent的狀態(tài)等,在這里也會(huì)將用戶的數(shù)據(jù)封裝在VO里面,再交由Command或Proxy來(lái)進(jìn)一步處理。基本上Mediator只對(duì)用戶的操作或用戶提交的數(shù)據(jù)進(jìn)行封裝并簡(jiǎn)單預(yù)處理,而業(yè)務(wù)邏輯,存儲(chǔ)服務(wù)的就應(yīng)交給Command和Proxy來(lái)做,這樣MVC分工好,使得程序結(jié)構(gòu)比較嚴(yán)緊,可讀性強(qiáng),實(shí)現(xiàn)松耦合。當(dāng)你改變了UI時(shí),只需要對(duì)Mediator進(jìn)行相應(yīng)的改變就行了,而你改變了業(yè)務(wù)的邏輯與算法之類的話,也相應(yīng)的改變Command就可以了,對(duì)其它模塊的影響不大。
          在上面這個(gè)圖中,沒(méi)有列出來(lái)的一個(gè)很重的類,就是 Notification 類,這個(gè)類為什么十分重要,可以說(shuō)也是PureMVC的潤(rùn)滑劑,因?yàn)樗沁B接MVC各大部分的一個(gè)消息機(jī)制,就像是Cairngome里面的CairngomeEvent與FrontController,為了實(shí)現(xiàn)更好的松耦合,就是靠這個(gè)消息機(jī)制,因?yàn)楦鞔蟛糠种校苌僦苯拥囊谜{(diào)用,而是以“發(fā)消息”(或者說(shuō)是通知吧)來(lái)相互數(shù)據(jù)交流與通訊,這里是很好的使用了“觀察者模式”,因此,在某一部分改變的處理邏輯的話,只是它所發(fā)送的消息沒(méi)有改變,或者所偵聽(tīng)的消息沒(méi)有改變,那么就不會(huì)影響到其它部分。
          另外要注意幾點(diǎn),Command類是短生命周期的,也就是說(shuō),當(dāng)有消息通知需要用到該Command進(jìn)行處理時(shí),F(xiàn)acade就會(huì)創(chuàng)建這個(gè)Command類,并將數(shù)據(jù)傳入Command里面進(jìn)行處理,當(dāng)處理完成后,其生命周期就會(huì)結(jié)束,所以不要將一些長(zhǎng)生命周期的數(shù)據(jù)存放在Command里,比如不要將一些狀態(tài)數(shù)據(jù)信息存放在Command里面。還有就是Proxy類只會(huì)發(fā)送“消息”(通知),而不會(huì)接收任何消息,而Mediator與Command則可以發(fā)送與接收,所以你不能直接發(fā)消息通知Proxy去加載數(shù)據(jù),而是通過(guò)引用Proxy的實(shí)例調(diào)用相關(guān)的函數(shù)。理論就說(shuō)了一大堆了,我們來(lái)看看那個(gè)MP3播放器實(shí)例吧!

    我們先來(lái)看看主程序的代碼,PureMVC的入口點(diǎn):
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
     3                 xmlns:view="com.jiangzone.flex.pureplayer.view.ui.*"
     4                 verticalGap="2"
     5                 layout="vertical" creationComplete="fadace.startup(this)"
     6                 backgroundColor="0x444444">
     7     <mx:Style>
     8         //這里的CSS代碼略去
     9     </mx:Style>
    10    
    11     <mx:Script>
    12         <![CDATA[
    13             import com.jiangzone.flex.pureplayer.ApplicationFacade;
    14            
    15             private var fadace:ApplicationFacade = ApplicationFacade.getInstance();
    16            
    17         ]]>
    18     </mx:Script>
    19     <mx:Box width="131">
    20         <view:ProgressBoard        id="progressBoard" />
    21         <view:ControlBoard         id="controlBoard" />
    22         <view:SongListBoard        id="songListBoard" />
    23     </mx:Box>
    24    
    25 </mx:Application>


    從上面代碼我們看到,定義了一個(gè) facade 這個(gè)就是Facade的一個(gè)實(shí)例,而ApplicationFacade是繼承自Facade類的,這個(gè)就是PureMVC的整個(gè)架構(gòu)的控制管理類,因?yàn)镕acade是一個(gè)單例,所以不能直接new 的,所以在ApplicationFacade里面定義了一個(gè)靜態(tài)方法來(lái)獲取它的實(shí)例。在程序的createComplete事實(shí)觸發(fā)的時(shí)候,我們就調(diào)用facade.startup(this)這個(gè)方法,意思就是啟動(dòng)整個(gè)框架。
    這里的代碼都比較簡(jiǎn)單,我們?cè)賮?lái)看看ApplicationFacade的代碼:

     1 package com.jiangzone.flex.pureplayer
     2 {
     3     import org.puremvc.as3.interfaces.IFacade;
     4     import org.puremvc.as3.patterns.facade.Facade;
     5     import org.puremvc.as3.patterns.observer.Notification;
     6    
     7     import com.jiangzone.flex.pureplayer.controller.StartupCommand;
     8    
     9     public class ApplicationFacade extends Facade implements IFacade
    10     {
    11         // Notification name constants
    12         public static const STARTUP:String             = "startup";
    13        
    14        
    15         /**
    16          * Singleton ApplicationFacade Factory Method
    17          */
    18         public static function getInstance() : ApplicationFacade {
    19             if ( instance == null ) instance = new ApplicationFacade( );
    20             return instance as ApplicationFacade;
    21         }
    22        
    23         /**
    24          * Start the application
    25          */
    26          public function startup(app:Object):void
    27          {
    28              sendNotification( STARTUP, app );   
    29          }
    30 
    31         /**
    32          * Register Commands with the Controller
    33          */
    34         override protected function initializeController( ) : void
    35         {
    36             super.initializeController();           
    37             registerCommand( STARTUP, StartupCommand );
    38         }
    39        
    40     }
    41 }


    這里分析一下,在ApplicationFacade類里,我們定義了一個(gè)String的常量,這個(gè)只是一個(gè)消息的類型,跟Flex里的Event的常量一樣的,注意,規(guī)范化一點(diǎn)的話,應(yīng)該將消息類型的字符串都定義為常量,而我在后面的代碼中為了省事就直接用“XXXXX”這樣的字串代替了,還是建義寫(xiě)成靜態(tài)常量。
    我們看到了startup()的代碼了,就是在剛才主程序里調(diào)用的那個(gè)函數(shù),這里接收了一個(gè)主程序的引用。
    我們還看到了有一個(gè)initializeController( ) 的函數(shù),當(dāng)這個(gè)ApplicationFacade被實(shí)例化加載的時(shí)候,會(huì)先自動(dòng)調(diào)用initializeController( ) 這個(gè)函數(shù),所以,我們應(yīng)當(dāng)在ApplicationFacade在被初始化的時(shí)候,就對(duì)Command進(jìn)行注冊(cè),說(shuō)就是注冊(cè),其實(shí)也只是將一個(gè)Command與一個(gè)消息綁定在一起而已。當(dāng)發(fā)送該消息時(shí),F(xiàn)acade就會(huì)自動(dòng)的找到那個(gè)Command并實(shí)例化執(zhí)行。
    registerCommand( STARTUP, StartupCommand );這句就是對(duì)Command進(jìn)行注冊(cè)的代碼,registerCommand都是父類或接口里面定義的方法,我們先不用管它,STARTUP就是上面定義的一個(gè)常量,表示一個(gè)消息的類型,StartupCommand這個(gè)類就是我定義的一個(gè)Command類,這里說(shuō)白了就是STARTUP這個(gè)字符串常量就是一個(gè)Key,而StartupCommand就是一個(gè)Value,存放在一個(gè)數(shù)組里面,當(dāng)有人發(fā)送一個(gè)STARTUP的消息時(shí),程序就自動(dòng)生成一個(gè)StartupCommand來(lái)處理。
    我們?cè)倏纯磗tartup()這個(gè)方法,在剛才的主程序里調(diào)用這個(gè)方法時(shí),傳入了一個(gè)傳入了一個(gè)參數(shù)this,就是主程序本身,在startup()方法里面,發(fā)送了一個(gè)消息 sendNotification( STARTUP, app );    sendNotification()這個(gè)是發(fā)送消息的方法,第一個(gè)參數(shù)是消息的類型,第二個(gè)是可選參數(shù),是消息的內(nèi)容(消息體),在這里,將主程序的引用作為消息體綁在消息里一起發(fā)送了。由于之前在初始化的時(shí)候?qū)TARTUP消息類型與StartupCommand綁定在一起了,所以當(dāng)發(fā)送這個(gè)消息的時(shí)候,StartupCommand將會(huì)被通知,所以這時(shí)候,程序的流程就跳入到StartupCommand類里面。下面我們來(lái)看StartupCommand類的內(nèi)容:

     1 package com.jiangzone.flex.pureplayer.controller
     2 {
     3     import org.puremvc.as3.interfaces.ICommand;
     4           //這里略去一些import代碼
     5     import com.jiangzone.flex.pureplayer.model.PlayListProxy;
     6    
     7     public class StartupCommand extends SimpleCommand implements ICommand
     8     {
     9         override public function execute( note:INotification ) : void   
    10         {
    11             /**
    12              * 獲取消息體內(nèi)容,在發(fā)送STARTUP消息時(shí),將主程序PurePlayer作為消息體跟隨消息傳送
    13              */
    14             var app:PurePlayer = note.getBody() as PurePlayer;
    15            
    16             /**
    17              * 注冊(cè)代理(Model)
    18              */
    19             facade.registerProxy(new SongProxy());
    20             facade.registerProxy(new PlayListProxy());
    21             /**
    22              * 注冊(cè)ViewComponents或者UI組件的中介器。
    23              */
    24              facade.registerMediator(new ControlBoardMediator(app.controlBoard));
    25              facade.registerMediator( new SongListBoardMediator(app.songListBoard));
    26              facade.registerMediator(new ProgressBoardMediator(app.progressBoard));
    27              
    28              (facade.retrieveProxy(PlayListProxy.NAME) as PlayListProxy).loadPlayList();
    29         }
    30     }
    31 }


    上面的就是一個(gè)Command的代碼,注意,一個(gè)Command必需要實(shí)現(xiàn)ICommand接口,而如果是一個(gè)單Command的話,就需要繼承SimpleCommand類,而如果是一個(gè)Command鏈的話,就需要實(shí)現(xiàn)MacroCommand,至于Command鏈,如果有J2EE基礎(chǔ)的話,也就是Filter的過(guò)濾器鏈差不多。這里不多說(shuō)。大家可以看看PureMVC的官方文檔與API!
    在Command里,都需要覆蓋execute 這個(gè)方法,這個(gè)方法就是執(zhí)行你的邏輯代碼的地方,由Facade自動(dòng)調(diào)用,當(dāng)這個(gè)Command所綁定的消息被發(fā)送時(shí),F(xiàn)acade就會(huì)創(chuàng)建一個(gè)Command實(shí)例并調(diào)用execute方法,方法里還傳入一個(gè)INotification參數(shù),就是你所發(fā)送的那個(gè)消息,里面包含了消息類型名稱與消息體。在這個(gè)Command里,我沒(méi)有處理什么,因?yàn)檫@個(gè)Command用于啟動(dòng)程序框架的,所以只在這里初始化了一些程序需要用到的資源,如注冊(cè)代理與注冊(cè)中介器,我們可以看到,注冊(cè)代理與注冊(cè)中介器的方法與注冊(cè)Command的方法不同,注冊(cè)Command的話,需要一個(gè)消息名稱與一個(gè)Command類綁定,而代理與中介器的注冊(cè)就不需要與消息綁定,直接將代理與中介器實(shí)例化之后進(jìn)行注冊(cè)就可以了。這是由于Command的生產(chǎn)控制不是由用戶來(lái)操作的,是由Facade里面的一個(gè)工廠方法來(lái)對(duì)Command實(shí)例化并管理的,所以需要與一個(gè)消息名稱進(jìn)行綁定,而代理與中介器就是用戶管理的,通常一個(gè)代理就對(duì)應(yīng)一個(gè)數(shù)據(jù)結(jié)構(gòu),如果有幾個(gè)數(shù)據(jù)結(jié)構(gòu)都比較簡(jiǎn)單,就可以在一個(gè)Proxy里管理,而同理,中介器也一樣,一個(gè)中介器對(duì)一個(gè)Flex組件,但為一個(gè)Button建立一個(gè)中介器未名太浪費(fèi)了,所以我這里都是將MP3分成三個(gè)部分,控制按鈕部分,歌曲列表部分,播放進(jìn)度部分,三個(gè)部分用三個(gè)中介器。通常這些中介器或者Proxy創(chuàng)建一次就可以了,F(xiàn)acade會(huì)將它它存放在數(shù)組中,當(dāng)需要用到時(shí),再由Facade來(lái)獲取他們,所以,在注冊(cè)代理與中介的時(shí)候,先實(shí)例化它們?cè)僮?cè)!因?yàn)镃ommand是短生命周期,而Proxy與Mediator是長(zhǎng)生命周期,所以這里與Command有點(diǎn)區(qū)別。在實(shí)例化中介器的時(shí)候,我傳入一個(gè)app.controlBoard的值:
    new ControlBoardMediator(app.controlBoard),就是說(shuō),我這個(gè)中介器是對(duì)應(yīng)app.controlBoard這個(gè)控件,app就是主程序。
    當(dāng)所有需要的資源都注冊(cè)好后,我執(zhí)行了下面一句代碼:
     (facade.retrieveProxy(PlayListProxy.NAME) as PlayListProxy).loadPlayList();
    之前講到,注冊(cè)代理時(shí),將代理的實(shí)例進(jìn)行注冊(cè),實(shí)際上就只是在Facade里將這個(gè)代理實(shí)例放進(jìn)數(shù)組里而已,所以用facade.retrieveProxy()這個(gè)方法可以再次獲得那個(gè)實(shí)例的引用,再調(diào)用這個(gè)代理里的一個(gè)方法loadPlayList()來(lái)進(jìn)行加載播放列表。上上上面已經(jīng)說(shuō)過(guò),因?yàn)镻roxy是只可以發(fā)信息,不可以收信息,所以你叫Proxy工作的話,只好得到它的引用再調(diào)用它的方法來(lái)控件它的工作。注意,在Facade重新獲得代理的方法里facade.retrieveProxy(PlayListProxy.NAME) as PlayListProxy  你需要指定一個(gè)字符串來(lái)獲取某一個(gè)代理,在編寫(xiě)每一個(gè)代理時(shí),都要為它指定一個(gè)name的字符串,而且是代理的唯一標(biāo)識(shí)!這個(gè)時(shí)候,程序的流程就會(huì)跳到代理里運(yùn)行l(wèi)oadPlayList()這個(gè)方法。下面,我們來(lái)看看PlayListProxy的代碼:

     1 package com.jiangzone.flex.pureplayer.model
     2 {
     3     import org.puremvc.as3.interfaces.IProxy;
     4           //省略import代碼
     5     import flash.xml.XMLNode;
     6 
     7     public class PlayListProxy extends Proxy implements IProxy
     8     {
     9         //定義一個(gè)代理的名字,唯一的標(biāo)識(shí)
    10         public static const NAME:String = 'PlayListProxy';
    11         //定義一個(gè)HttpService,用于獲取遠(yuǎn)程的數(shù)據(jù)
    12         private var hs:HTTPService;
    13        
    14         public function PlayListProxy():void{
    15             super(NAME,new Array());
    16             hs = new HTTPService();
    17             hs.addEventListener(ResultEvent.RESULT,onResult);
    18             hs.addEventListener(FaultEvent.FAULT,onFault);
    19         }
    20        
    21         public function get playList():Array{
    22             return data as Array;
    23         }
    24        
    25         public function loadPlayList(url:String = 'jiang/pureplayer/data/playlist.xml'):void{
    26             hs.method = "GET";
    27             hs.resultFormat = "xml";
    28             hs.url = url + '?ranid=' + (new Date()).time;
    29             hs.send();
    30         }
    31        
    32         private function onFault(e:FaultEvent):void{
    33 
    34         }
    35        
    36         private function onResult(e:ResultEvent):void{
    37             var arr:Array = data as Array;
    38             var xmlNode:XMLNode = e.result as XMLNode;
    39             for(var i:String in xmlNode.childNodes){
    40                 var obj:Object = new Object();
    41                 var node:XMLNode = xmlNode.childNodes[i];
    42                 obj["label"= node.attributes.label;
    43                 obj["data"= node.attributes.data;
    44                 arr.push(obj);
    45             }
    46             sendNotification("GET_PLAYLIST_COMPLETE",data);
    47         }
    48     }
    49 }


    很累呀。。。休息一會(huì),抽根煙繼續(xù)!

    來(lái)分析一下代碼,在該代理被實(shí)例化時(shí),會(huì)調(diào)用super(NAME,new Array());這個(gè)父類的方法,其實(shí)Proxy的構(gòu)造函數(shù)接收兩個(gè)參數(shù),一個(gè)是Proxy的唯一標(biāo)識(shí)名字,另一個(gè)就是所需要作代理的數(shù)據(jù),是一個(gè)Object,就是說(shuō),你的這個(gè)Proxy類要對(duì)哪些數(shù)據(jù)作代理呢?就是這個(gè)值傳入的,在Proxy基類里面有一個(gè)data的屬性,這個(gè)屬性就是存放你的實(shí)際數(shù)據(jù),所以在我的這個(gè)PlayListProxy構(gòu)造時(shí),我創(chuàng)建了一個(gè)Array來(lái)作為我的數(shù)據(jù),因?yàn)槲疫@個(gè)代理,是代理一個(gè)播放列表數(shù)據(jù)的,所以我將用Array來(lái)存放我的播放列表數(shù)據(jù)。所以就將new Array()的值交給父類構(gòu)造器里,父類構(gòu)造器將會(huì)對(duì)該Array存放在data這個(gè)變量屬性里。由于data是Object類型的,所以我們獲取這個(gè)data的時(shí)候,還要對(duì)其轉(zhuǎn)換成相應(yīng)的類型,所以為了方便,我寫(xiě)了一個(gè)getter方法來(lái)封裝這個(gè)操作:
    1 public function get playList():Array{
    2     return data as Array;
    3 }

    以后可以直接調(diào)用playList屬性來(lái)獲取Array類型的數(shù)據(jù)了。
    而在 loadPlayList 這個(gè)函數(shù)里,接收一個(gè)可選參數(shù)url,通過(guò)HttpService來(lái)獲取該url中的xml數(shù)據(jù)。
    按照上上上上上面說(shuō)的那樣,Proxy只有一個(gè),但你可以按不同用途分為L(zhǎng)ocal Proxy,與Remote Proxy,而這里它的作用就是Remote Proxy,因?yàn)樗遣僮鬟h(yuǎn)程數(shù)據(jù)。
    當(dāng)接收數(shù)據(jù)成功時(shí),調(diào)用了 onResult 方法,里面進(jìn)行了XML簡(jiǎn)單的分析,其實(shí)可以將該分析操作交給一個(gè)Command來(lái)完成,但是這里確實(shí)是太簡(jiǎn)單的分析了,就沒(méi)有必交給Command了,自已來(lái)完成吧。當(dāng)解析完成時(shí),發(fā)送了一個(gè)消息sendNotification("GET_PLAYLIST_COMPLETE",data);
    這里要說(shuō)明一下,這里用了發(fā)消息來(lái)通知其它模塊說(shuō)我已獲得數(shù)據(jù)了,你們誰(shuí)對(duì)這個(gè)數(shù)據(jù)有興趣就拿去吧。(本人覺(jué)得這樣理解更有趣并容易理解)由于是這個(gè)機(jī)制,所以無(wú)論你界面怎樣改變,中介器怎樣改變,都不會(huì)影響到我Proxy,因?yàn)槲耀@得數(shù)據(jù)時(shí),我不用引用你某一個(gè)中介器(如果中介器改變了,則同時(shí)要修改Proxy的代碼),我只發(fā)送一個(gè)消息,你們要?jiǎng)t要,不要?jiǎng)t罷,所以你界面如何改變的話,只要接收這個(gè)消息就可以同樣的得到了數(shù)據(jù),而不用因界面的修改而修改Proxy。這樣就可以將Mediator與Proxy松耦了。
    至于,是誰(shuí)對(duì)這個(gè)“GET_PLAYLIST_COMPLETE”感興趣呢?我在上上上面說(shuō)過(guò),Proxy只會(huì)發(fā),不會(huì)收,所以肯定不是其它Proxy對(duì)這消息有興趣,而Command么,Command感興趣的消息都是在Facade里給綁定的,而我們上上上面的代碼中,F(xiàn)acade只綁定了STARTUP這個(gè)消息,所以現(xiàn)在唯一下來(lái)的,就是中介器了,因?yàn)橹薪槠饕彩强梢允张c發(fā)消息的。如果一個(gè)中介器(或者說(shuō)一個(gè)界面組件吧)對(duì)一個(gè)消息感興趣的話,那就需要在中介器的類里面定義這些感興趣的消息,下面我們來(lái)看看一個(gè)ControlBoardMediator的中介器的代碼:
     1 package com.jiangzone.flex.pureplayer.view
     2 {
     3     import org.puremvc.as3.patterns.mediator.Mediator;
     4     import org.puremvc.as3.interfaces.IMediator;
     5     import com.jiangzone.flex.pureplayer.view.ui.SongListBoard;
     6     import flash.events.MouseEvent;
     7     import mx.events.ListEvent;
     8     import org.puremvc.as3.interfaces.INotification;
     9     import mx.controls.List;
    10     import mx.collections.ArrayCollection;
    11 
    12     public class SongListBoardMediator extends Mediator implements IMediator
    13     {
    14         public static const NAME:String = "SongListBoardMediator";
    15        
    16         public function SongListBoardMediator(vc:Object):void{
    17             super(NAME,vc);
    18             songListBoard.songList.doubleClickEnabled = true;
    19            
    20             songListBoard.songList.addEventListener(ListEvent.ITEM_DOUBLE_CLICK,onDoubleClick);
    21         }
    22        
    23         public function get songListBoard():SongListBoard{
    24             return viewComponent as SongListBoard;
    25         }
    26        
    27         public function get songList():List{
    28             return songListBoard.songList;
    29         }
    30        
    31         private function onDoubleClick(e:ListEvent):void{
    32             var str:String = (e.target.selectedItem.data as String);
    33             sendNotification("GET_SONG_URL_COMPLETE",str);
    34         }
    35        
    36         override public function listNotificationInterests():Array{
    37             return [
    38                        "GET_SONG_URL",
    39                        "GET_PREV_URL",
    40                        "GET_NEXT_URL",
    41                        "GET_PLAYLIST_COMPLETE"
    42                    ];
    43         }
    44        
    45         override public function handleNotification(note:INotification):void{
    46             switch(note.getName()){
    47                 case "GET_SONG_URL":
    48                     if(songList.selectedItem)
    49 
    50 
    51                         sendNotification("GET_SONG_URL_COMPLETE",songList.selectedItem.data as String);
    52                     break;
    53                 case "GET_PREV_URL":
    54                     if(songList.selectedItem){
    55                         var i:int = songList.selectedIndex;
    56                         i -= 1;
    57                         if(i<0) i = (songList.dataProvider as ArrayCollection).length - 1;
    58                         songList.selectedIndex = i;
    59                         sendNotification("GET_PREV_URL_COMPLETE",songList.selectedItem.data as String);
    60                     }
    61                     break;
    62                 case "GET_NEXT_URL":
    63                     if(songList.selectedItem){
    64                         var i:int = songList.selectedIndex;
    65                         i = (i + 1% (songList.dataProvider as ArrayCollection).length;
    66                         songList.selectedIndex = i;
    67                         sendNotification("GET_PREV_URL_COMPLETE",songList.selectedItem.data as String);
    68                     }
    69                     break;
    70                 case "GET_PLAYLIST_COMPLETE":
    71                     var arr:Array = note.getBody() as Array;
    72                     songList.dataProvider = arr;
    73             }
    74         }
    75     }
    76 }


    在這份代碼中,我們主要看看幾個(gè)方法函數(shù),其它的都只是處理邏輯,控制Sound的播放什么的,與PureMVC關(guān)系不大了。我們主要看看這幾個(gè)方法:
    override public function listNotificationInterests():Array
    override public function handleNotification(note:INotification):void
    先說(shuō)第一個(gè)方法,這個(gè)方法返回的是一個(gè)數(shù)組,我們上面說(shuō)到,怎么知道中介器對(duì)哪些消息感興趣呢?就在這個(gè)方法里設(shè)置了,這些都是接口里的方法,所以需要override,在這個(gè)方法里,直接返回一個(gè)字符串?dāng)?shù)組就可以了,而那些字符串,就是你的消息名稱 的字符串,剛才Proxy中,處理完數(shù)據(jù)后,發(fā)了一個(gè)“GET_PLAYLIST_COMPLETE”的消息,并將處理好的數(shù)據(jù)作為消息體一起發(fā)送出去了。
    而在這個(gè)Mediator里的listNotificationInterests里,返回一個(gè)
    1 return [
    2     "GET_SONG_URL",
    3     "GET_PREV_URL",
    4     "GET_NEXT_URL",
    5     "GET_PLAYLIST_COMPLETE"
    6 ];

    看到?jīng)]有?那個(gè)數(shù)組里面包含了GET_PLAYLIST_COMPLETE這個(gè)消息名稱字符串。所以,當(dāng)有人發(fā)送這個(gè)消息時(shí),這個(gè)中介器就會(huì)進(jìn)行響應(yīng),至于對(duì)這個(gè)消息的響應(yīng)程序,就在
    override public function handleNotification(note:INotification):void
    這個(gè)方法里面寫(xiě)上消息響應(yīng)代碼。
    在響應(yīng)函數(shù)里,都用switch(note.getName())來(lái)區(qū)分處理它所接收到的消息的名稱,再處以不同的處理代碼。

    好了,基本上,整個(gè)PureMVC的結(jié)構(gòu)就這樣了,流程是比較簡(jiǎn)單,就是用消息(Notification)來(lái)圍繞MVC各個(gè)部分模塊來(lái)開(kāi)發(fā)。這個(gè)程序還有其它的中介器類,代理類還有其它的類就不一一列出來(lái)了,反正PureMVC工作方式都是一樣的,只是對(duì)應(yīng)的功能邏輯不一樣。

    呼,終于全部寫(xiě)完了,下面給出整個(gè)Flex Project 的 源代碼:
    [down=http://www.jiangzone.com.cn/attachments/month_0806/t200864163352.zip]點(diǎn)擊下載此文件[/down]



    posted on 2008-07-29 14:44 姜大叔 閱讀(4992) 評(píng)論(32)  編輯  收藏 所屬分類: Flash/Flex

    評(píng)論:
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2008-08-10 11:27 | 魚(yú)
    好崇拜哦!!
    樓主,源代碼下載不了哦,能發(fā)一份給我嗎?目前我很需要,拜托樓主!!!我的Email:cjc19762338@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-08-10 16:13 | sqw00453579
    好厲害啊``我也想學(xué)習(xí)```可以給個(gè)源代碼嗎```謝謝了```
    我的郵箱``sqw00453579@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-08-20 14:37 | HUIHUI
    的確厲害。 我想學(xué) 我也要個(gè)源碼 3Q~~~
    我的郵箱:huiqian1984@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-09-04 21:58 | zdcgh
    sysucgh#163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-09-16 10:07 | nova
    向你請(qǐng)教一個(gè)問(wèn)題:用swfloader載入一個(gè)swf文件,當(dāng)這個(gè)swf文件中有一個(gè)combbox的話,這個(gè)combox會(huì)有問(wèn)題。具體就是,在第二次load這個(gè)文件的時(shí)候,里面的combox不能正常使用,不知道你遇到過(guò)嗎?不知你是否能給我指點(diǎn)。
    tieying-sky@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2008-10-28 10:52 | 魚(yú)
    求一份源文件!!
    Email:wwj256@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2008-11-04 13:59 |
    求得一分源文件。~謝謝
    zhouyanjie@cdeledu.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-11-05 14:40 | CALM
    求一份源文件。~謝謝
    calm7@sohu.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-11-12 14:38 | 530705296@qq.com
    你好,源碼不能下載啊,是否網(wǎng)址有錯(cuò),發(fā)一份到我的郵箱530705296@qq.com好嗎?謝謝》  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-11-12 22:40 | 小亂
    求源文件
    yunaiming3@163.com
    萬(wàn)分感激~~~~~~~~~~~~  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2008-12-02 16:48 | 副萊克斯
    恩,源碼不能下載 ,也給我發(fā)一份源碼吧 cjf868@163.com
    萬(wàn)分感謝!!!  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2008-12-13 10:57 | 風(fēng)
    樓主 真是大好人啊 你的這些講解讓我對(duì)PureMVC 有了進(jìn)一步的了解

    感動(dòng)  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-03-13 18:59 | ltdainiy
    源碼不能下載 ,也給我發(fā)一份源碼吧 ltdainiy@163.com
      回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-03-31 09:11 | anither
    源碼不能下載,樓主也給我發(fā)一份吧 anither@sohu.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-04-16 20:57 | 長(zhǎng)沙滿哥
    zan yi ge  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-05-14 16:00 | ideadawn
    不知道博主還能看見(jiàn)我的回復(fù)不,看見(jiàn)的話也麻煩給我U一份吧,謝謝了,ideadawn@126.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-05-25 03:45 | wxz
    完整看了博主的這篇文章,還有有些疑惑,能否email一份源代碼給我,萬(wàn)分感激!wxz859681117@yahoo.com.cn  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2009-07-12 12:34 | dave
    如果可以的話,也請(qǐng)樓主發(fā)一份完整代碼給我,謝謝
    davesong07@gmail.com
      回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-07-16 15:43 | pyd
    樓主都發(fā)了那么多份了,也發(fā)份給小弟我吧
    急需,麻煩您了
    pyd1053@163.com
    不勝感激啊。。。。。。。  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-07-23 11:06 | 王國(guó)金
    您好,樓主,你的源碼不能下載,請(qǐng)你發(fā)給我一份好嗎?
    king_wgj@hotmail.com
    謝謝你了!  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-10-22 13:43 | sdd
    不錯(cuò),給我一份,整學(xué)習(xí)中

    kevin51job@hotmail.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2009-11-01 14:22 | beyondpaul
    能給我一份源代碼嗎

    連接失效了··感謝 你


    25893458@qq.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2009-11-08 18:02 | 渴望
    給我一份吧,謝謝
    xyxc.105@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2010-04-02 10:36 | JAM
    講解得很精辟, 樓主一定把源碼看過(guò)了吧,要是能把框架的源碼結(jié)合進(jìn)去說(shuō)明下,想必條理能夠更清晰.   回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2010-07-21 15:49 | 我要源代碼
    求源代碼
    huangfang20065128@163.com
    感謝 你……  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2010-12-13 10:38 | iLinux
    代碼需求好踴躍  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2012-04-23 22:33 | 輕淌
    樓主都發(fā)了那么多份了,也發(fā)份給小弟我吧
    15891448250@163.com
    不勝感激啊。。。。。。。  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2012-05-09 14:35 | 王斌
    我只想說(shuō),樓主真犀利啊,樓主辛苦了哈  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2013-01-29 18:02 | hugangyong
    寫(xiě)得還可以,但我補(bǔ)充幾點(diǎn):mvc的好處和壞處,每個(gè)貼,每個(gè)人講的都大同小異,大家可以找?guī)讉€(gè)看看。但是從管理學(xué)和風(fēng)險(xiǎn)上來(lái)講,mvc框架做到了以人為本,因地制宜,何解,很多情況下開(kāi)發(fā)團(tuán)隊(duì)的人員的經(jīng)驗(yàn)和特長(zhǎng)不一,作為一個(gè)好的項(xiàng)目經(jīng)理,如果運(yùn)用好這把利劍,那么,他們每個(gè)人將發(fā)揮自己的優(yōu)勢(shì),鍛煉自己的信心,對(duì)人的發(fā)展最有利,其他的好處我不說(shuō)了,我打個(gè)比方,一個(gè)剛從學(xué)校畢業(yè)的有熱情有求知欲但是目前能力不夠的人,如果從縱面上給他分配開(kāi)發(fā)任務(wù),這基本上是浪費(fèi)了人才的同時(shí)增大了風(fēng)險(xiǎn),最大的弊病是對(duì)人的發(fā)展極為不利,這樣的結(jié)果有三種,一:此人壓力過(guò)大,走人,二:此人沒(méi)有完成任務(wù),三:此人在別人的幫助下勉強(qiáng)的完成了任務(wù),但耗費(fèi)了很多不必要的時(shí)間。上面幾種情況對(duì)人的成長(zhǎng)和信心的是不小的毀滅。但是從橫向面上則不一樣,界面的樣式不需要很懂業(yè)務(wù),并且可以很快的開(kāi)發(fā)修改,并且有效果,即我們的v,時(shí)間有限,這里就不繼續(xù)講了  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析[未登錄](méi) 2013-03-24 15:59 | hua
    求源碼啊樓主!
    hua14300@163.com  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2014-09-25 16:38 | rong
    有沒(méi)有源碼提供啊,多謝!!!  回復(fù)  更多評(píng)論
      
    # re: 基于PureMVC的一個(gè)Flex MP3播放器分析 2014-09-25 16:38 | rong
    272914287@qq.com
    能不能發(fā)份源碼到我郵箱啊,萬(wàn)分感謝!!  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 亚洲a级片在线观看| 日韩免费视频播放| sss日本免费完整版在线观看| 亚洲人片在线观看天堂无码| 亚洲综合在线一区二区三区 | 国产91精品一区二区麻豆亚洲| 日韩免费视频播播| 亚洲国产高清在线| 亚洲天堂久久精品| 国产青草亚洲香蕉精品久久| 色天使亚洲综合一区二区| 老司机午夜在线视频免费观| 免费人人潮人人爽一区二区| 羞羞视频免费网站日本| 成人国产精品免费视频| 西西人体免费视频| 最近免费mv在线电影| **俄罗斯毛片免费| 99视频在线精品免费观看6| 亚洲性线免费观看视频成熟 | 免费鲁丝片一级在线观看| 国产精品四虎在线观看免费 | 国产精品亚洲综合一区在线观看| 国产午夜精品久久久久免费视| 久久久久国色av免费看| 亚洲黄色片免费看| 中文亚洲AV片在线观看不卡| 久久91亚洲精品中文字幕| 亚洲综合色7777情网站777| 黄色毛片视频免费| 欧亚精品一区三区免费| 内射少妇36P亚洲区| 亚洲人成网站日本片| jizzjizz亚洲日本少妇| 国产精品入口麻豆免费观看| 国产精品成人无码免费| 亚洲中文字幕久在线| 免费A级毛片av无码| 国产成人3p视频免费观看 | 国产精品成人观看视频免费| 亚洲成色www久久网站夜月|