`
friendsys
  • 浏览: 338835 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

PureMVC笔记

阅读更多
PureMVC的核心
一:Model保存对Proxy对象的引用,Proxy负责操作数据模型,与远程服务通信存取数据。
二:View保存对Mediator对象的引用。由Mediator对象来操作具体的视图组件包括:添加事件监听器,发送或接收Notification ,直接改变视图组件的状态。
三:Controller保存所有Command的映射。Command可以获取Proxy对象并与之交互,通过发送Notification来执行其他的Command。

我们要所要做的是编写具体的Command,Mediator,Proxy
一:Proxy是负责操作数据模型的,什么是数据模型?数据模型就是数据库,XML等等。我们可以直观地理解为,Proxy是用来对数据模型进行查询插入、更新、删除等操作的类。操作完成后,它就会发送Notification,也就是通知,告诉其它两个层我已经完成工作了。
二:Mediator负责操作具体的视图组件,包括:添加事件监听器,发送或接收Notification ,直接改变视图组件的状态。好像抽象了点。具体的说吧,Mediator是负责管理用户界面,与用户进行交互操作的
三:Command可以获取Proxy对象并与之交互,通过发送Notification来执行其他的Command

使用get和set方法封装对象,实现内部的类型转换,方便的进行变量的转换,也可以提供部分的数据




自己的笔记
记录搭建的过程

1:新建一个类,继承facade,用于作为初始化系统的核心类,里面包括了MVC类的包装和初始化
在这个类中,需要定义2个静态的字符串常量,一个用于表示启动命令,一个用于demo中的登陆命令
然后实现一个静态的方法,用于表示单例模式,名字应该随意,不过为了好表示,用getInstance():返回一个当前类类型
下面记录下例子
public static function getInstance():MyFacade
{
if(instance==null)instance=new MyFacade();
return instance as MyFacade;
}
然后定义一个starup方法,用于传入Application对象,初始化全局Facade对象,该方法在Application的createComplete进行
该方法的调用.主要就是发送一个Notification,其中参数为表示Notification类型名STARTUp常量,传递进来的Application
例子如下
sendNotification(STARTUP,app);

第三个,就是重写一个protected方法 initializeController,用于进行Command的注册,记得调用super父类中的该方法
super.initializeController();
registerCommand(LOGIN,LoginCommand);
registerCommand(STARTUP,StartUpCommand);

其中只在facade中注册Command,将proxy和Mediator的注册放在了StartUP的Command中进行定义

对应的Command设计如下,
PureMVC下的Command分为两种,一种是MacroCommand,另外的一种是SimpleCommand,其中MacroCommand中通过重写
protected方法initializeMacroCommand中通过调用,addSubCommand(SimpleCommand类名)进行多个Command的组合

其中StartUp过程中 就是使用MacroCommand进行初始化了Model和View,也就是Mediator类与Proxy类
然后主要的Facade类,就基本初始化完成了

这里的问题是,为啥不把Model和View的初始化也放在Facade中完成,虽然可以放在外部,不过感觉StartUP这个Command比较多余
,还是要多看看PDF的那个文档

然后开始介绍Statup这个Command中初始化View和Model的过程
再调用那个MacroCommand后,进入到Model的初始化过程,其实也就是调用了对应的SimpleCommand去进行对应的初始化
例子中首先进行了主Application的Mediator的初始化过程,通过在Notification中获取到body对象进行
var app:MyPureMVC=note.getBody() as MyPureMVC;
facade.registerMediator(new MyFacadeMediator(app));
由于StartUP中的Command,只传递给主程序Application的引用,所以只进行了Application的Mediator初始化
其中Notification,并不直接创建,只是通过send方法进行发送,并且附带三个参数,名称,对象,类别.
其中对象为Object,所以使用的时候,需要进行类型转换,其中就涉及到了隐性的setter和getter方法,
在注册Mediator过程中,使用类中的定义的常量进行初始化,用于后期获取,Proxy也是使用类似的方法

其他的Mediator初始化,放在主Application的Mediator的构造函数中,因为其中可以获取到主Application的引用,可以获取到
主Mxml中的public对象和组件,方便传递不同的组件,用于初始化对应的组件的Mediator

同时进行Proxy的注册,这个相对比较简单,只要在execute方法里面
facade.registerProxy(new LoginProxy());

这里主要要点SimpleCommand的execute方法是public的

在StartUPCommand的处理过程中也会涉及到M和V的初始化过程,下面开始介绍

先说相对简单的Proxy对象
通过继承Proxy来定义对应的LoginProxy类,用于包装数据的请求操作,
默认的构造方法有两个参数,不过都可以为空
其中第一个为NAME一个字符串,第二个为Object类型,都可以使用null来做默认值
在构造函数中调用super的父类构造函数
构造函数中参数用于生成对应名称的Proxy,便于在其他地方进行引用,然后生成对应的对象
Name为常量,表示获取该对象时候使用的名称,其中使用public Static const常量

其中常用一个VO对象作为构造函数的一部分,demo就用到了New LoginVO对象
在父类的构造函数中,会自动将类中的data=构造函数中的VO对象,在其他地方时候的时候,不用考虑当前是什么名称,只要
直接调用data对象即可,也可以直接使用隐形getter进行便捷的对象获取
Proxy中其他作用.封装了其他的数据请求的方法,用于和后台RemoteObject交互等等,以及他们的事件,
不过调用Proxy的地方定义在Command中,不直接监听Notification,当异步处理好交互后,在回调事件中调用sendNotification发送消息
进行对应的处理,例子
sendNotification(LOGIN_SUCCESS,loginVO); 其中第一个参数为发送的消息名,用于在监听Notification中进行对应的判断调用
,第二个为Notification的body方法所返回的对象,

很好的封装了数据请求,好处之一就是防止了单个mxml文件过大.导致维护困难,

接下来介绍 Mediator中的构建过程
构造函数中包含了一个名称为viweComponent的组件对象,常对应与程序中的一个组件,比如Panel等
也和Proxy一样,定义了一个常量的Name,用于动态的获取,以及一个组件,就是构造函数传入的,
在父类的构造函数中,会将该组件正式命名为一个viewComponent对象,同样也可以使用隐形的getter进行类型转换,方便处理
Mediator主要的方法介绍---是需要进行重写的方法
listNotificationInterests()方法,用于设定监听Notification通知,和使用的观察者模式有关,其中的数组名称,就是Proxy中
sendNotification出的第一个参数,使用类名.常量进行引用

handleNotification()方法中接受一个通知的参数,就是根据上个方法得到的对应的INotification对象,在方法中使用switch
进行note.getName()的调用,判断不同的名称,进行对应的操作,因为能够获取到组件,所以调整显示页面会很方便.
其他部分就是与Component的交互,主要是事件的监听,这样也减少了component中function的数量,便于维护和设计页面
一般在构造函数中,进行事件的监听,需要先设置隐形getter转换viewComponent然后.addlistener(),进行指定的事件监听,这里涉及到
了自定义事件的使用,不完全使用flex的自带事件,严格的说是封装了原始事件,进行2次触发,不依赖原有事件类型,也涉及到了VO驱动的
设计.

这里介绍下自定义匿名事件,以及监听的方式.通过局部的VO的Bindable 进行VO驱动的开发
事件的定义
public static const TRY_LOGIN:String="tryLogin";  用于定义个常量...用于提供监听的目标名
然后使用dispatchEvent(new Event(TRY_LOGIN)) 进行该事件的触发,一般放置在组件的事件内,2次触发指定事件
在Mediator中监听loginPanel.addEventListener(LoginPanel.TRY_LOGIN,handlerTryLogin); 进行事件的处理

View和Proxy的交互流程,通过Command中转...
由于设计的考虑,在Proxy中不直接监听Notification,所以要在View中进行发送sendNotification,然后调用对应的Command
,sendNotification(MyFacade.LOGIN,loginPanel.loginVO);
并且传递对应的参数,其中的第一个参数为在Facade中注册的Command名字,也是全局静态常量

最后介绍下Proxy的获取方式,用于在Command中调用
var loginProxy:LoginProxy=facade.retrieveProxy(LoginProxy.NAME) as LoginProxy;
根据注册的NAME来获取指定的Proxy,并且调用相关的方法,用于在外部调用Proxy进行交互,Proxy处理后,通过sendNotification来
发送事件,在Mediator中进行触发调用,其中的参数对象,主要用到的是第二个Object参数

Command和常量注册后,就可以使用sendNotification来发送调用命令
可是Command能够调用Proxy中的方法,Command还有其他什么用途么 除了进行初始化Proxy和Mediator外

还有为什么不在Mediator里面直接调用Proxy,难道是为了可重用
可以考虑将初始化v和M的放置在一个SimpleCommand里面,便于管理和节约代码,放置在两个方法就好,放置在两个文件也可以,就是类多了

使用自定义事件的好处,减少耦合,包括了减少代码修改的次数

MacroCommand的作用在于按照顺序执行Command,并且传递同一个Notification的引用
Command的作用中包括,获取Proxy和Mediator对象,并直接操作他们

在注册一个实例的时候,需要调用一个类的实例进行,Command只要类型,前者使用facade来调用,后者定义在主facade类中
facade.registerProxy( new UsersProxy() );

注册Mediator过程中,第一个要注册就是主Mxml文件,通过startup方法,发送Notification,调用Command,然后注册
facade.registerMediator( new ApplicationMediator( app ) );  通过Notification.getBody()来传入参数,不过似乎不进行转换
也是可以的.
这个是唯一一个在Command中注册的Mediator,其他的Mediator都在这个Mediator中进行注册,因为这个Mediator中可以获取到其他的
View Component的引用,所以构建都放在Application对应的Mediator的构造函数中创建

Command的业务逻辑应该避免被Model或View的变化影响,面向接口编程

有一句话可以关注下,
因为Mediator也会经常和Proxy交互,所以经常在Mediator的构造方法中取到Proxy实例的引用,并保存在Mediator的属性中,这样可以避免频繁的获取Proxy的实例

Mediator被构造后,也可以通过调用它的setViewComponent函数来动态给他的ViewComponent赋值(修改)

如果多个Mediator对同一个事件做出响应,那应该发送一个Notification,然后相关的Mediator做出各自的相应,监听的好处

如果一个Mediator需要和其他的Mediator进行大量的交互,那么一个好的方法利用Command把交互步骤定义在一个地方

不应该让一个Mediator直接去获取调用其他的Mediator,那怎么去获取其他的Mediator呢,难道都放置在一个Command里面

Proxy可以发送Notification给Mediator,将数据的变化反映到视图上

业务逻辑应该放置Command中,而非Mediator中.在Proxy发送消息的时候需要考虑到这点

一般一个Mediator(handleNotIfication方法)处理的Notification应该在4,5个左右

对于在Mediator中定义的事件方法,应该只是发送Notification,而不应该处理复杂的逻辑,也不应该涉及到太多的ViewComponent细节,
应该对视图ViewComponent的处理,尽可能的封装起来----总结就是使用自定义事件类型包装ViewComponent里面的处理结果,然后在Mediator
中只要监听自定义事件类型即可.

通过Command进行Mediator和Proxy的操作,可以实现v和m之间的松耦合

如果一个Mediator要和其他的Mediator交互,应该选择发送一个Notification,让目标进行接受,这样减少耦合,而不是直接引用Mediator来操作

ViewComponent里面应该封装复杂的控件操作,只暴露一个方法,提供可重用性.

Command也应该这样进行封装,用于提高可重用性

可以继承Proxy,然后实现不同通信方式的封装,达到可重用的目的
通常Proxy Pattern有一下几种类型,
1:RemoteObject Proxy 2:Proxy and Delegate 3:Protection Proxy 4:Virtual Proxy 5:Smart Proxy

Proxy构造函数默认需要2个参数,第一个是名称,第二个是Object类型的参数,
其中Object可以用setDate进行修改数据模型

正确的分层操作,目的还是提高重用性,减少开发时间

在 Flash/Flex 环境中,我们可能会使用HTTPService,WebService,RemoteObject,DataService 或者
XMLSocket 来从 Proxy 中发送服务请求。 

技巧:通过setData(event.result)来变更data内容,用于隐形的转换对象数据









分享到:
评论
4 楼 friendsys 2009-06-04  
文章的字体 这个可以通过浏览器进行设置的,网页上的CSS只是个参考.
Model层的方法可以直接在Mediator层中实例化一个进行调用,或者使用Command都可以
3 楼 zalbelieve 2009-06-04  
强烈建议把文章的字体放大点 看着好辛苦啊 呵呵
2 楼 zalbelieve 2009-06-04  
你调用model层的方法怎么在mediator层调用啊?应该在注册一个xxCommand吧,然后在这个里去调用model层的方法吧!!呵呵...
1 楼 zalbelieve 2009-06-04  
这篇文章写得好啊!!看懂啦差不多!!还得再看一次才行啊!!爽!!

相关推荐

Global site tag (gtag.js) - Google Analytics