初探PureMVC:使用PHP+MySQL+Flex结合PureMVC框架做了个Flex留言本

PureMVC框架听也听得多了,但自己一直没有着手去弄过。最近有必要学习它了,于是在各种搜索引擎找了一些资料,现在总算对这个框架有所了解。眼高手低是不行的,所以自己动手去实践一下了。OK!弄一个留言本试试看,然后自己再详细地分析了一下,希望对PureMVC框架有更深的一层了解。我写的不是教程哦,是总结。所以哪里写得不好,请原谅,也恳请您能指出哪里不好。下面只介绍了这个留言本在开始时从服务端获取数据的工作流程,先看下面那个流程图,接着奉上详细的代码以及注释,最后提供源文件下载。

PureMVC Flex 留言簿流程图

 

Main.mxml

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--
  3.    
  4.     初探PureMVC, 学习理论后, 实践最重要. 如果发现一些不恰当的地方, 请到以下地方指出来:
  5.    
  6.     My Blog : riaoo.com
  7.     My Email: y_boy@126.com & riahome.cn@gmail.com
  8.    
  9.     谢谢!
  10.    
  11.     注意: 本例子使用了 PHP + MySQL, 为了测试成功, 请在虚拟环境下测试. 测试前, 请先创建数据库, 需要创建的数据库在 "sql" 文件夹里了.
  12.           欢迎交流!
  13.    
  14. -->
  15. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
  16.     xmlns:UI="cn.riahome.guestbook.puremvc.view.UI.*"
  17.     creationComplete="facade.startup( this )" fontSize="12">
  18.    
  19.     <!--
  20.        
  21.         目前分析途径: Main.mxml
  22.         完整分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  23.        
  24.         整个pureMVC框架就是从上面那个 startup() 函数开始了, 正如其名, 它启动了整个框架.
  25.         请按着 Ctrl 键点击这个函数, 进入去看代码.
  26.      -->
  27.    
  28.     <mx:Style>
  29.         .errorTip{
  30.             fontSize:12;
  31.         }
  32.     </mx:Style>
  33.    
  34.     <mx:Script>
  35.         <![CDATA[
  36.            
  37.             import cn.riahome.guestbook.puremvc.ApplicationFacade;
  38.            
  39.             private var facade:ApplicationFacade = ApplicationFacade.getInstance();
  40.            
  41.         ]]>
  42.     </mx:Script>
  43.    
  44.     <UI:ListPanel id="listPanel" x="71" y="10" width="555" height="498"/>
  45.    
  46.     <UI:InsertPanel id="insertPanel" x="634" y="318" width="400" height="190"/>
  47.    
  48.     <UI:DetailPanel id="detailPanel" x="634" y="10" width="400" height="300"/>
  49.    
  50. </mx:Application>

 

ApplicationFacade.as

 

  1. package cn.riahome.guestbook.puremvc
  2. {
  3.     import cn.riahome.guestbook.puremvc.controller.StartupCommand;
  4.    
  5.     import org.puremvc.as3.interfaces.IFacade;
  6.     import org.puremvc.as3.patterns.facade.Facade;
  7.  
  8.     public class ApplicationFacade extends Facade implements IFacade
  9.     {
  10.         /**
  11.          *
  12.          * 目前分析途径: Main.mxml -> ApplicationFacade.as
  13.          * 完整分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  14.          *
  15.          * 来到这里, 有必要说一下 MVC, 即 Model, View, Controller:
  16.          *
  17.          * Model:
  18.          *     model => 数据! 本人觉得在 pureMVC 里, model 里有两个主角: VO(Value Object) 和 Proxy(代理).
  19.          *     VO 是数据的结构, 存储数据的容器. 一条留言(TopicVO)就有ID值(id), 留言时间(addTime), 昵称(username), 内容(content)
  20.          *     Proxy 是负责获得数据的. 获得数据的方式有很多种, 可以获得本地数据(swf本身里的数据), 也可以从互联网上获得数据, 当然从服务器上获得数据也是常发生的事情.
  21.          *           而从非本地获得数据可以是: http, remote...
  22.          *
  23.          * View:
  24.          *     view => 显示! 顾名思义, view 就是显示的东西. 一切要显示的东西都在这里了. 通常, 它也会有两个主角: UI 和 Mediator(中介器)
  25.          *     UI 就是那些要显示的东西, 例如一个显示留言的界面(就是一个component), 一个填写留言的界面(也是一个component)
  26.          *     Mediator 最最最重要的任务是处理有关 UI 的逻辑. 比如说更新 UI 上显示的数据, 或者是提交数据, 又或者是验证用户输入的数据
  27.          *
  28.          * Controller:
  29.          *     controller => 逻辑! controller, 里头都是一个命令(Command), 一些算法, 一些逻辑就在这里头完成.
  30.          *     Model 的 Proxy 获得数据后, 可能需要把这些数据进行一些处理, 那就交由 Controller 里的那些 Command 处理吧.
  31.          *     Model 的 Proxy 只负责着获得数据, 具体的数据处理交给 Controller 的 Command 吧
  32.          *     例如: Proxy 获得的数据可能是 变量/值 配对格式的数据, 而我需要的是 xml 格式的, 那就需要实现转化了. 转化过程就交给 command 了.
  33.          *
  34.          * 总的来说:
  35.          *     View 用于显示东西给用户看的, 显示的数据由 Model 提供. 有时候 Model 获得的数据不一定就合 View 的胃口,
  36.          *     那么 Model 先把数据交给 Controller 处理好, 处理好后再交给 View 显示出来.
  37.          *
  38.          * 那么, Model 是在什么时候把数据交给 View 层呢? 又是怎样来交给 View 呢? 就是通过发布 "通知" 来实现的, 这个通知携带着数据. 这是 pureMVC 的消息机制.
  39.          *
  40.          * 无论您有没有弄懂以上所说的, 都请您先把它记住!
  41.          *
  42.          * 以下定义了一些通知, 当这个通知发布出去时, 对这个通知感兴趣的 Command 或者 Mediator 会接收这个通知.
  43.          *
  44.          **/
  45.         public static const STARTUP:String = "startup";
  46.        
  47.         public static const GET_ALL_TOPIC_COMPLETE:String = "getAllTopicComplete"; // ListPanel 对这个通知感兴趣
  48.         public static const SELECT_TOPIC:String = "selectTopic"; // DetailPanel 对这个通知感兴趣
  49.         public static const INSERT_TOPIC_COMPLETE:String = "insertTopicComplete"; // ListPanel 对这个通知感兴趣
  50.        
  51.         /**
  52.          * 以下这个函数是采用单例模式, 也就是整个 swf 就只有它一个
  53.          **/
  54.         public static function getInstance():ApplicationFacade
  55.         {
  56.             if( instance == null ) instance = new ApplicationFacade();
  57.             return instance as ApplicationFacade;
  58.         }
  59.        
  60.         /**
  61.          * 下面就是启动整个 pureMVC 的函数
  62.          * sendNotification() 函数用来发布通知的, 这份通知书里装着数据的.
  63.          * 第一个参数是通知书的标题(是一个唯一的标识符), 第二个参数是携带的数据(是MVC三者之间传递的数据).
  64.          **/
  65.         public function startup( app:Object ):void
  66.         {
  67.             sendNotification( STARTUP, app );
  68.         }
  69.        
  70.         /**
  71.          * 重写这个函数, 您也看到了, 使用 registerCommand() 函数来用注册 command 的.
  72.          * 何谓 "注册 Command" 呢? 就是使 "通知" 跟 command 对应起来.
  73.          * 下面就是把通知名 STARTUP 跟 StartupCommand 对应起来.
  74.          * 在任何时候任何地方, STARTUP 通知被发布了, StarupCommand 就会被执行.
  75.          * 每一个 command 里头都有一个 execute() 函数的, execute() 函数的参数由谁来充当呢?
  76.          * 就是通知所携带的数据, 也就是上面 sendNotification() 函数的第二个参数.
  77.          *
  78.          * 好了, 从 Main.mxml 文件里的 creationComplete="facade.startup( this )" 语句中走到这里了,
  79.          * 现在得从 registerCommand( STARTUP,  StartupCommand ) 语句中走到 StartupCommand 里了.
  80.          * 请您按着 Ctrl 键点击一下 StartupCommand.
  81.          **/
  82.         override protected function initializeController():void
  83.         {
  84.             super.initializeController(); // 先调用父类的 initializeController() 方法, 看 pureMVC 源代码可知, 调用这个方法会创建一个单例的 controller, 具体自己看了.
  85.             registerCommand( STARTUP StartupCommand );
  86.         }
  87.        
  88.     }
  89. }

 

StartupCommand.as

 

  1. package cn.riahome.guestbook.puremvc.controller
  2. {
  3.     import cn.riahome.guestbook.puremvc.model.InsertTopicProxy;
  4.     import cn.riahome.guestbook.puremvc.model.ListTopicProxy;
  5.     import cn.riahome.guestbook.puremvc.view.DetailPanelMediator;
  6.     import cn.riahome.guestbook.puremvc.view.InsertPanelMediator;
  7.     import cn.riahome.guestbook.puremvc.view.ListPanelMediator;
  8.    
  9.     import org.puremvc.as3.interfaces.ICommand;
  10.     import org.puremvc.as3.interfaces.INotification;
  11.     import org.puremvc.as3.patterns.command.SimpleCommand;
  12.    
  13.     /**
  14.      *
  15.      * 目前分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as
  16.      * 完整分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  17.      *
  18.      * 一旦收到通知 STARTUP 后, 就会执行这个 StartupCommand.
  19.      * 收到的通知里头携带着数据, 这个数据作为参数传递给下面那个 execute() 函数了.
  20.      *
  21.      * 在这里, 主要的功能是注册 Model 里的 Proxy(代理) 和 Controller 里的 Mediator(中介器)
  22.      * 看看 execute() 函数里的代码, 无论是注册 Proxy 还是 Mediator, 都是由 facade 对象的 registerProxy() 方法或 registerMediator() 方法完成的
  23.      * facade 对象是本类内部的一个家伙, 用来管理 Proxy 和 Mediator 的. 在后面的代码里, 想要重新获得 Proxy 或者 Mediator 都可以通过这个 facade 家伙.
  24.      * 是不是对这个 facade 对象感到很奇怪呢!? 如果想知道更多, 就得看 pureMVC 框架的源代码了. 在这里简要说一下:
  25.      *     facade 是一个单例对象, 也就是说整个 swf 只有孤独的它一个. 在你写的 Proxy, Mediator 以及 Command 里都会有它的存在. 用它来管理 Proxy 和 Mediator 的.
  26.      *     就像最下面那行代码 ( facade.retrieveProxy( ListTopicProxy.NAME ) as ListTopicProxy ).getAllTopic();
  27.      *     可以通过使用 retrieveProxy() 方法来找回相应的 Proxy, 要找回某个 Proxy, 就要传递那个 Proxy 的名字进去.
  28.      *     类似地, 也有 retrieveMediator() 方法来找回 Mediator.
  29.      *     在 facade 内部是使用数组来存放这些 Proxy 和 Mediator 的. 为什么能找到指定的 Proxy 或 Mediator 呢?
  30.      *     那是因为每一个 Proxy 或 Mediator 都有它自己的一个名字, 那个数组存储 Proxy 或 Mediator 时, 是使用它们自身的名字来作为键(Key)进行存储的.
  31.      *     要找到指定的 Proxy 或 Mediator, 只需知道它的名字就可以了.
  32.      **/
  33.    
  34.     public class StartupCommand extends SimpleCommand implements ICommand
  35.     {
  36.         /**
  37.          * 这个函数要重写啊.
  38.          **/
  39.         override public function execute(note:INotification):void
  40.         {
  41.             /**
  42.              * 下面两个 Proxy 是用来与服务端通讯的. 它们负责着数据的 获取 或 提交.
  43.              * InsertTopicProxy 是用来向服务端提交数据的, ListTopicProxy 是用来获取数据的.
  44.              *
  45.              * 您可以按着 Ctrl 键点击 ListTopicProxy, 看看它的内部如何
  46.              **/
  47.             facade.registerProxy( new InsertTopicProxy() );
  48.             facade.registerProxy( new ListTopicProxy() );
  49.            
  50.            
  51.             /**
  52.              * 记住, Mediator 是负责 UI(就是那些 component)的逻辑部分.
  53.              * 不管是数据验证, 更新 UI 所显示的数据, 还是其它乱七八糟的东西, 都由每块UI(就是每块 Component)所对应的 Mediator 来处理的.
  54.              * 例如: InsertPanelMediator 负责把对应的 InsertPanel(这是一个 component) 里的数据进行检验(对用户输入的数据进行检验正确与否),
  55.              *      检验无误后, 就把数据交给 InsertTopicProxy 写入数据库. 而 UI(一个component) 本身不进行任何的数据处理或逻辑分析等等.
  56.              **/
  57.             var app:Main = note.getBody() as Main;
  58.             facade.registerMediator( new InsertPanelMediator( app.insertPanel ) );
  59.            
  60.             /**
  61.              * 完整分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  62.              * 先去分析 ListTopicProxy.as 再来看以下那个 ListPanelMediator.
  63.              **/
  64.             facade.registerMediator( new ListPanelMediator( app.listPanel ) );
  65.            
  66.             facade.registerMediator( new DetailPanelMediator( app.detailPanel ) );
  67.            
  68.             /**
  69.              * 有些数据是在一开始的时候就需要的, 所以在这里就命令 ListTopicProxy 调用它的方法 getAllTopic() 来取得服务端上的数据.
  70.              * 通过 facade 对象的 retrieveProxy() 方法来找回指定的 Proxy.
  71.              * 在这里找回了 ListTopicProxy, 因为我把这个 ListTopicProxy 的名字作为参数传递进 retrieveProxy() 方法了.
  72.              *
  73.              * 以下代码可以拆分为:
  74.              * var proxy:ListTopicProxy = facade.retrieveProxy( ListTopicProxy.NAME ) as ListTopicProxy;
  75.              * proxy.getAllTopic();
  76.              **/
  77.             ( facade.retrieveProxy( ListTopicProxy.NAME ) as ListTopicProxy ).getAllTopic();
  78.         }
  79.     }
  80. }

 

ListTopicProxy.as

 

  1. package cn.riahome.guestbook.puremvc.model
  2. {
  3.     import cn.riahome.guestbook.puremvc.ApplicationFacade;
  4.     import cn.riahome.guestbook.puremvc.model.vo.TopicVO;
  5.    
  6.     import flash.net.URLVariables;
  7.    
  8.     import mx.collections.ArrayCollection;
  9.     import mx.controls.Alert;
  10.     import mx.messaging.messages.HTTPRequestMessage;
  11.     import mx.rpc.events.FaultEvent;
  12.     import mx.rpc.events.ResultEvent;
  13.     import mx.rpc.http.HTTPService;
  14.    
  15.     import org.puremvc.as3.interfaces.IProxy;
  16.     import org.puremvc.as3.patterns.proxy.Proxy;
  17.  
  18.     public class ListTopicProxy extends Proxy implements IProxy
  19.     {
  20.         /**
  21.          *
  22.          * 目前分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as
  23.          * 完整分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  24.          *
  25.          * 为这个 Proxy(这里为ListTopicProxy) 起一个名字. 这个名字是唯一的, 且应该定义为静态的常量.
  26.          **/
  27.         public static const NAME:String = "ListTopicProxy";
  28.        
  29.         private var httpService:HTTPService;
  30.        
  31.         public function ListTopicProxy()
  32.         {
  33.             /**
  34.              * 每一个 Proxy 都有一个 data 属性, 用来存储需要传递的数据, 就是用来携带数据的.
  35.              * 这里必须先调用父类的构造函数, 把自己的名字和携带的 数据/数据类型 传进父类的构造函数
  36.              * 下面传递的第二个参数是一个 ArrayCollection, 当执行 super() 后, data(Object类型)属性就会变为一个 ArrayCollection.
  37.              **/
  38.             super(NAME, new ArrayCollection() );
  39.            
  40.             /**
  41.              * 在每个 Proxy 里面, 一定要做的事情就是上面的两项: 为自己起一个名字 以及 先调用父类的构造函数
  42.              * 然后具体要做的事情, 就根据需要而定了.
  43.              * 这里要做的事是: 从服务端获取留言数据, 当获取数据完成后, 就发布一个通知来告诉大家:"我完成了向服务端获取留言数据了,我拥有这些数据".
  44.              * 您看看下面的 onResult() 函数, 该函数里有一条语句: sendNotification( ApplicationFacade.GET_ALL_TOPIC_COMPLETE, data ).
  45.              * 第一个参数就是通知消息, 以静态常量的方式在 ApplicationFacade 类里定义了.
  46.              **/
  47.            
  48.             httpService = new HTTPService();
  49.             httpService.method = mx.messaging.messages.HTTPRequestMessage.GET_METHOD;
  50.             httpService.resultFormat = HTTPService.RESULT_FORMAT_XML;
  51.             httpService.url = "php/listTopic.php"; // 这里的 url 根据您的虚拟目录不同而不同
  52.             httpService.addEventListener( ResultEvent.RESULT, onResult );
  53.             httpService.addEventListener( FaultEvent.FAULT, onFault);
  54.         }
  55.        
  56.         private function onResult( event:ResultEvent ):void
  57.         {
  58.             var arr:ArrayCollection = new ArrayCollection();
  59.             var result:XMLList = XML( event.result ).children();
  60.            
  61.             for( var i:uint = 0; i < result.children().length(); i++)
  62.             {
  63.                 var o:TopicVO = new TopicVO( result[i].@id, result[i].@addTime, result[i].@username, result[i] );
  64.                 arr.addItem( o );
  65.             }
  66.            
  67.             data = arr;
  68.             /**
  69.              * 通知: 各单位注意, 我完成了向服务端获取留言数据了,我拥有这些数据, 有意者请接收通知!
  70.              * 在这个例子里, 希望得到这些数据的当然是 ListPanel.mxml 了.
  71.              * 但, 之前已经说过, 取得数据这类的工作并不用 UI(也说是component) 来完成, 这些工作由 UI 的中介器(Mediator)来完成.
  72.              * 在这里, ListPanel.mxml 的中介器是 ListPanelMediator.
  73.              * 现在, 请您打开 ListPanelMediator.as 文件, 或者在 "分析途经" 路线上退回上一级(也就是 StartupCommand.as 文件),
  74.              * 然后找到 facade.registerMediator( new ListPanelMediator( app.listPanel ) ) 这一句,
  75.              * 按着 Ctrl 键点击 ListPanelMediator, 进入去看看源码.
  76.              *
  77.              * 目前 分析途经: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as
  78.              *
  79.              **/
  80.             sendNotification( ApplicationFacade.GET_ALL_TOPIC_COMPLETE, data );
  81.         }
  82.        
  83.         private function onFault( event:FaultEvent ):void
  84.         {
  85.             Alert.show( event.message.toString(), "提示");
  86.         }
  87.        
  88.         public function getAllTopic():void
  89.         {
  90.             httpService.send( new URLVariables("ran="+Math.random()) ); // 给一个随机参数, 避免缓存
  91.         }
  92.     }
  93. }

 

ListPanelMediator.as

 

  1. package cn.riahome.guestbook.puremvc.view
  2. {
  3.     import cn.riahome.guestbook.puremvc.ApplicationFacade;
  4.     import cn.riahome.guestbook.puremvc.model.ListTopicProxy;
  5.     import cn.riahome.guestbook.puremvc.view.UI.ListPanel;
  6.    
  7.     import mx.collections.ArrayCollection;
  8.     import mx.events.ListEvent;
  9.    
  10.     import org.puremvc.as3.interfaces.IMediator;
  11.     import org.puremvc.as3.interfaces.INotification;
  12.     import org.puremvc.as3.patterns.mediator.Mediator;
  13.  
  14.     public class ListPanelMediator extends Mediator implements IMediator
  15.     {
  16.         /**
  17.          *
  18.          * 目前分析途经: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  19.          * 完整分析途径: Main.mxml -> ApplicationFacade.as -> StartupCommand.as -> ListTopicProxy.as -> ListPanelMediator.as
  20.          *
  21.          * 以下是给自己一个唯一的名字, 通过 facade 对象的 registerMediator() 方法找回自己时, 就得用这个唯一的名字了.
  22.          * **/
  23.         public static const NAME:String = "ListPanelMediator";
  24.        
  25.         public function ListPanelMediator( viewComponent:Object )
  26.         {
  27.             /**
  28.              * 调用父类的构造函数, 第一个参数传入自己的名字, 上面只是起了名字, 还没写入户口薄或身份证哩, 调用 super() 后才算是写入户口薄.
  29.              * 如果您是按着 "分析途经" 看过来的话, 那您就应该在 StartupCommand.as 里看过, 应该知道每个 UI(component) 都有一个对应的 Mediator.
  30.              * 在这里, 这个 ListPanelMediator 就是为那个 ListPanel.mxml 服务的. super() 函数的第二个参数就是指明为哪个 UI(component) 服务.
  31.              * 那么参数 viewComponent 是在哪里开始传入的呢? 大家回顾 StartupCommand.as 文件, 在注册 ListPanelMediator 时就已经传入了 app.listPanel.
  32.              * app 是 主文件(Main.mxml)的引用, listPanel 是 app 里的一个 UI(component).
  33.              * 也就是说, 从一开始在 StartupCommand.as 里注册自己(ListPanelMediator)时, 就已经指明了自己是为哪个 UI(component) 服务的.
  34.              *
  35.              * 看 "分析途经", 上一级的 ListTopicProxy.as 成功获取服务端的数据后, ListPanel.mxml 急切地想得到那些数据,
  36.              * 但 取得数据 这项工作是由它的中介器(就是本类 ListPanelMediator)来完成的.
  37.              *
  38.              * 上一级的 ListTopicProxy.as 成功获取服务端的数据后, 发布通知, 说已经成功获取数据了.
  39.              * 然后到了这里, 在这里是怎样接收那个通知的呢? 又是怎样为对应的 UI(component) 完成上述工作的呢?
  40.              * 请看下面的 listNotificationInterests()函数 和 handleNotification()函数. 第一个实现如何接收通知, 第二个实现相应工作.
  41.              **/
  42.             super( NAME, viewComponent );
  43.            
  44.             listPanel.dataGrid.addEventListener( ListEvent.ITEM_CLICK, onSelect );
  45.         }
  46.        
  47.         // 通知: 各单位注意, 用户现已选择了一条留言, 需要接收通知的单位请马上接收.
  48.         private function onSelect( event:ListEvent ):void
  49.         {
  50.             sendNotification( ApplicationFacade.SELECT_TOPIC, listPanel.dataGrid.selectedItem );
  51.         }
  52.        
  53.         // 获得对应的 UI(component)
  54.         public function get listPanel():ListPanel
  55.         {
  56.             return viewComponent as ListPanel;
  57.         }
  58.        
  59.         /**
  60.          * 在下面的函数里列出了所以感兴趣的通知, 包括: GET_ALL_TOPIC_COMPLETE 和 INSERT_TOPIC_COMPLETE.
  61.          * 上一级的 ListTopicProxy.as 成功获取服务端的数据后, 发布这个通知: GET_ALL_TOPIC_COMPLETE.
  62.          * 因为本类对这个通知感兴趣, 所以当通知(GET_ALL_TOPIC_COMPLETE)一旦被发布了(不管发布是谁), 本类马上接收了该通知,同时取得该通知所携带的数据.
  63.          * 接收到通知后, 就进入最下面的 handleNotification() 函数了.
  64.          *
  65.          * (只要把感兴趣的通知放入下面函数的数组里, pureMVC 内部就会把通知从发布者送到接收者手上了. 有兴趣可以打开 pureMVC 的源代码看看内部机制)
  66.          **/
  67.         override public function listNotificationInterests():Array
  68.         {
  69.             return [
  70.                     ApplicationFacade.GET_ALL_TOPIC_COMPLETE,
  71.                     ApplicationFacade.INSERT_TOPIC_COMPLETE
  72.                     ];
  73.         }
  74.        
  75.         /**
  76.          * 以下函数的参数 note 就是那个通知了. 姑且把那个通知叫做通知书, 所以在这个通知书里有两个重要信息: 通知书名称(通知类型) 和 通知书里的内容(通知书所携带的数据).
  77.          * 如何分别取得通知(note)的类型和它所携带的数据呢? 可以这样:
  78.          *     通知类型: note.getName()
  79.          *     通知携带的数据: note.getBody()
  80.          *
  81.          * 以下函数就是根据接收到的通知类型而采取不同措施. 比如说, 接收到 ListTopicProxy 发布的 GET_ALL_TOPIC_COMPLETE 通知, 于是执行 switch 语句的第一个分支.
  82.          * switch 语句的第一个分支的功能是: 更新对应的 UI(这里是 listPanel, 一个component) 里的数据.
  83.          * 在 listPanel 里先定义好一个 topicData 变量, 给中介器操作.
  84.          * 相当于在 UI 里提供一个接口给中介器操作, 这样就把 表现层(UI) 跟 逻辑层(Mediator) 分开了, 伟人说这是 松偶合 !
  85.          *
  86.          * 如何取得对应的 UI(component) 呢? 就在上面的那个 getter 函数取得: public function get listPanel():ListPanel{}
  87.          *
  88.          * 到此为止, 一个完整的 pureMVC 工作原理在 "分析途径" 上算是表现出来了.
  89.          * 来到这里, 如果你通过本例子弄懂了 pureMVC 工作原理, 那恭喜您! 也恭喜我! 您是聪明的, 我也是聪明的:)
  90.          *
  91.          * 欢迎一起交流技术:
  92.          *         My Blog : riaoo.com
  93.          *         My Email: y_boy@126.com & riahome.cn@gmail.com
  94.          **/
  95.         override public function handleNotification(note:INotification):void
  96.         {
  97.             switch( note.getName() )
  98.             {
  99.                 case ApplicationFacade.GET_ALL_TOPIC_COMPLETE:
  100.                     listPanel.topicData = note.getBody() as ArrayCollection;
  101.                     break;
  102.                
  103.                 case ApplicationFacade.INSERT_TOPIC_COMPLETE:
  104.                     ( facade.retrieveProxy( ListTopicProxy.NAME ) as ListTopicProxy ).getAllTopic();
  105.                     break;
  106.             }
  107.         }
  108.        
  109.     }
  110. }

源文件下载:PureMVC_GuestBook.zip

posted on 2012-04-22 22:08  ycty  阅读(1641)  评论(4编辑  收藏  举报