Flex观察者模式
来源:互联网 发布:ds18b20与单片机连接图 编辑:程序博客网 时间:2024/06/05 19:15
假设以下场景:
Application中有两个Panel:PanelA和PanelB,其中PanelA是主界面,用到的数据模型为ModelA,PanelB是从PanelA跳转过来的,用到的数据模型为ModelA和ModelB。
分为三个步骤:
- PanelA请求数据。
- PanelA和PanelB处理数据。
- 用户操作从PanelA跳转到PanelB。
这里只讨论使用设计模式的情况,那些不使用设计模式的方法不在谈论之列。
Cairngorm
Cairngorm是一个比较简单的微框架,基本思想是把命令的请求者和命令的执行者分开。
请求者通过发送CairngormEvent来执行命令,而执行者就是一个Command,而它们之前的关联关系则通过FrontController进行初始化,隐藏在FrontController后面的则是一个单例的CairngormEventDispatcher类。
Cairngorm的这种方式就是一个典型的观察者模式:
- Actionscript3本身就有个观察者模式的实现——EventDispatcher。
- Cairngorm对其进行了一层封装,把观察者模式中的Subject(即Actionscript3中的EventDispatcher)封装到CairngormEventDispatcher中,而观察者模式中的attach/detach操作则封装在FrontController中。
- 而Subject的调用方就是上面说的命令的请求者。
回到上面的场景的步骤1,PanelA请求ModelA的数据时需要发送一个CairngormEvent,而对应的Command接收到ModelA后,有两个方向:
- Command把ModelA放到PanelA和PanelB中。
- Command通知PanelA和PanelB数据已经准备好在某个地方,PanelA和PanelB去某个地方获取ModelA。
如果用方法1,Command需要知道PanelA和PanelB的引用,实现这个有很多方法(如通过全局变量存储、PanelA和PanelB的引用通过CairngormEvent对象传到Command中),明显,这些都不是好方法,最重要的一个原因是Command需要知道使用ModelA的具体对象。
方法2,就是一观察者模式。Command不需要知道ModelA的具体使用对象,不管是PanelA、PanelB,还是后来多了一个PanelC。Command只需要发送一个完成的通知即可。
到这里可以看到,一个视图要执行一个命令(步骤1)是通过发送一个CairngormEvent,以此将视图和Command实现松耦合,而现在(步骤2)则需要Command发送一个通知所有需要使用ModelA的视图。
PureMVC
PureMVC是另外一个常用的Actionscript3 MVC框架,但使用上要比Cairngorm复杂得多。故我一直比较抗拒PureMVC。
- PureMVC对于每个视图View都需要创建一个对应的Mediator,对于每个模型Model都需要创建一个对应的Proxy,外加若干个Command作为控制器。
- 调用时是通过一个单例Facade对象(多核心版的PureMVC实现了多个单例,但我觉得使用更麻烦了)。
- 所有的Mediator、Proxy、Command都可以互相调用,内部关系非常复杂,要理清一个比较大的项目的Mediator、Proxy、Command之间的调用关系不是那么容易的。
对于步骤1和步骤2,如果使用PureMVC,首先PanelA和PanelB分别对应一个Mediator,ModelA和ModelB分别对应一个Proxy:
- Facade初始化时先依次注册Command、Proxy和Mediator。
- Facade发送通知,执行Command。
- Command初始化Proxy的属性。
- Proxy发送通知。
- Mediator接收到Facade发送过来的通知,通过Proxy获取到Model,然后更新对应的Panel。
=====================================================================================
我在面试那些应聘Flex开发职位的应聘者的时候,如果他了解PureMVC,我除了问PureMVC的基本框架思想外,我都会问两个问题:
- 你觉得PureMVC为什么叫Pure?
- PureMVC的notification和Cairngorm的CairngormEvent的区别是什么?
这两个问题其实是相通的。
=====================================================================================
我的做法
对于文章一开始的场景的设计,步骤1(发送命令请求)我个人比较推崇用Cairngorm,而步骤2(接收返回数据并展现)我习惯于利用EventDispatcher。
PureMVC由于没有利用Actionscript3中内置的观察者模式的实现(EventDispatcher),而是创造了notification这种与语言无关的实现。
使用EventDispatcher,对于步骤2的实现,也可以有两个途径:
- EventDispatcher放到模型中。
- EventDispatcher放到一个独立的中介者Mediator中。
EventDispatcher放到模型中
ArrayCollection就内置了一个EventDispatcher,当List持有一个ArrayCollection对象,如果ArrayCollection对象发生了改变,则List会做出相应的变化。
步骤2中,PanelA和PanelB就必须在调用请求命令之前就持有ModelA的对象,而Command只是修改ModelA的属性值。
EventDispatcher放到一个独立的中介者Mediator中
如果PanelA和PanelB在调用请求命令之前没有持有ModelA的对象,则Command可以把创建的ModelA对象传送给Mediator,Mediator通知PanelA和PanelB,而一个持有ModelA对象的Event对象需要贯通这个过程。具体流程如下:
- PanelA和PanelB通过Mediator监听事件eventA,并注册监听方法funcA和funcB。
- Command创建ModelA后,创建事件eventA,eventA持有ModelA对象,并通过Mediator发送出去。
- Mediator接收到eventA后,调用观察者PanelA和PanelB的注册方法,即funcA(eventA)和funcB(eventA)。
- funcA更新PanelA,funcB更新PanelB。
方法二可以把方法一合并进来,即ModelA中内置一个EventDispatcher,PanelA和PanelB就可以监听ModelA的变化。
步骤3
步骤3是两个视图之间的交互,显而易见,还是可以利用上面用到的Mediator实现松耦合。
总结
- 设计模式只是一种工具,一种经验积累的成果,不能为了模式而模式。
- 不能局限于设计模式,视图之间的交互不一定用中介者模式,也可以用观察者模式,或者其它模式,只要模式合适。
- 要认清PureMVC的优缺点,轻易别用PureMVC。
- 可以多使用和参考Actionscript3内置的一些特点和Flex的一些官方做法。
- Flex观察者模式
- Flex设计模式思考——观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- Oracle10g for AIX 安装实施文档
- Ajax中的XMLHttpRequest对象详解
- Oracle中null的使用详解
- ARP ARP攻击查找
- iPhone开发经典语录集锦
- Flex观察者模式
- 什么是流?
- GetTokenInformation出错
- 按钮全选
- ansi,unicode,gb2312,utf-8编码之间的区别
- 远程医疗系统发展分析
- Unity3D 批量图片资源导入设置
- 从30岁到35岁:为你的生命多积累一些厚度
- android XML文件使用