??xml version="1.0" encoding="utf-8" standalone="yes"?>
2. 增加LocaleQ错误信息的国际化的处理?br>d了一个Properties文gQ?br>d了com.adobe.cairngorm.CairngormMessageCodes和com.adobe.cairngorm.CairngormError两个c,其中CairngormMessageCodes用于定义Properties文g中的键|而CairngormError装了ErrorQ在应用执行的过E不再直接抛出ErrorQ而抛Z个CairngormErrorQ其中带一个参数就是MessageCodeQ根据MessageCode到Properties文g中取出相应的消息?/p>
3. 在business中,d了一个IServiceLocator的接?br>ServiceLocator实现IServiceLocator接口Q相比以前增加了以下几个ҎQ?br>a、public function getRemoteObject( serviceId : String ) : RemoteObject // Return the RemoteObject for the given service id.
b、public function getHTTPService( serviceId : String ) : HTTPService // Return the HTTPService for the given service id.
c、public function getWebService( serviceId : String ) : WebService // Return the WebService for the given service id.
d、public function getConsumer( serviceId : String ) : Consumer // Return the message Consumer for the given service id.
e、public function getProducer( serviceId : String ) : Producer // Return the message Produce for the given service id.
f、public function getDataService( serviceId : String ) : DataService // Return the DataService for the given service id.
g、public function setCredentials( username : String, password : String ) : void // Set the credentials for all registered services. Note that services that use a proxy or a third-party adapter to a remote endpoint will
原来的getService和getInvokerServiceҎ已经废弃Q改ZgetRemoteObject
4. 在Command中,增加了ICommand接口Q原来的Command接口l承ICommand
5. 在VO中,增加了IValueObject接口Q原来的ValueObjectl承IValueObject接口
上面d的几个接口,除了IServiceLocator相较2.0版本有了较大的变化,增加了一些方法,其他的几个接口,依我所见,Ua是换了名字而已?/p>
Cairngen是一个Caringorm的代码生成器, 它得开发者可以很方便地生成Cairngorm目的结构框? 包括: Cairngorm目的目录结? 一个缺省的ModelLocator, Controller, ServiceLocator. Cairngen也可以生成Event, Command, Delegatec?
Cairngen使用Flex2和PHP5.2.0开? 利用了AMFPHP. 安装q程十分方便. 你可以在Flex Builder的浏览器中直接运行Cairngen来快速方便地生成Cairngorm的类.
Cairngen使用'步骤(Sequence)'来描qEvent, Command, DelegatecM间的关系.
在Cairngen中只要命名一?步骤',点击一下生成按钮就可以生成一?步骤'. 然后h一下Flex目, 生成的类OK? 在一些特D的情况? 你不希望dDelegatec? 那么你可以选择排除Delegatecȝ生成, q样的话, Cairngen只生成Event和Command.
生成的Commandcd现Cairngorm的Command接口, 但不实现IResponder接口. Cairngenq能够正地事件强制性{?casting)为Coand中的cd, qimport所有相关的c?
pȝ需?
1. 了解AMFPHP, Apache2.0.59和PHP5.2.0, 在用Cairngen之前要求先安装AMFPHP, 而且gateway.php的访问虚拟目录应该如下设|? http://localhost/amfphp/gateway.php. ?.0版正式发布后, q个URL可以自由配置.
2. q需要安装Flex2, PHP, 你可以用WAMP5来集成安装Apache5.5和PHP. 安装好PHP和AMFPHP? 可以解压羃Cairngen Alpha 1. 把services目录复制到amfphp的根目录? 然后复制cairgen-ui目录到apache的www根目录下.
使用:
安装好PHP和AMFPHP? 可以开始用Cairngen? 打开览器输?a href="http://localhost/cairngen-ui/Cairngen.html">http://localhost/cairngen-ui/Cairngen.html打开生成器的囑Ş界面. 创徏Cairgen目:
点击 begin
l你的Cairngen目命名. q个名称与Flex目的名U相? 选择你的Cairngorm的版? 选择Flex目的\? 讄目中包路径(比如: com.domain.projectname). 最? 验一下输入内? 点击"Create Project". hFlex目查看~省的Cairngorm目l构, ModelLocator, Service和Controllerc?
创徏"步骤":
首先是给步骤命名, 然后选择是否要生成Delegatec? 点击生成, q刷新Flex目. 可以发现需要的cdl生成完毕了. 现在需要把它们d到Controller?
接下来编辑模板文? 你可以修Ҏ板文?.tpl)来实C的特定的Cairngorm需? 模板文g?amfphp\services\com\ericfeminella\cairngen\templates目录?
生成器下载地址: http://code.ericfeminella.com/cairngen/Cairngen%20Alpha%201%20PreRelease.zip
3) 也不要用*cd?/p>
4) 不要ActionScript的类声明为动态?/p>
5) 注意Application.application (和其他的无类型的框架属?. q个属性有一些古? 他应该是Applicatoncd的,因ؓ他指向的实例必须是Application的子c? 但实际上他的cd?Object', 无法应用~译时的查。如果你一定要用,最好也q行cd的强制性{换?
MyApplication( Application.application ).functionCall();
6) 装你的Xml。用Xml与Serverq行数据的交互非常方便,但是量避免使用Xml作ؓ核心数据模型。从服务器收到数据后Q尽量把Xml转换为强cd的对象模型。在Flex应用内部使用Xml是绕开~译器的作法?
7) 不要使用DynamicEvent.
8) 不要使用mx:Model。如上所qͼ请尽量用自定义的强cd的类.
9) 不要使用Cairngorm中的data属性,而应该承扩展CairngormEvent来传递数据?/p>
10) 不要把编译器的严格模式关?/p>
在Flex的开发过E中Q尤其是在用Cairngorm的时候,M遇到需要在Model的属性值改变后Q需要调用一个指定的函数。传l的解决Ҏ是用一个SetterҎQ在q个Ҏ中首先对属性赋|然后调用指定的函敎ͼ比如Q?/p>
---------------------------
[ChangeEvent("deleteEnabledChange")]
public function get deleteEnabled() : Boolean {
return _deleteButtonVisible;
}
public function set deleteEnabled(value : Boolean) : Void {
_deleteButtonVisible = value;
SimpleButton(deleteButton)._visible = false;
dispatchEvent(new Event("deleteEnabledChange", this));
}
--------------
但是现在我们有一个更z的解决之道
首先dq样一个类
package com.adobe.ac.util
{
public class Observe
{
public var handler : Function;
public function set source( source : * ) : void
{
handler.call();
}
}
}
然后可以用这个作为标{了?br /><util:Observe source="{ model.myProperty }"
handler="{ this.myFunction }"/>
使用了这L一个标{Q今后嘦是对model.myPropertyq行赋|׃调用myFunction
q个L世上最的标签是不是很好用啊?
增加验证
我们现在d对股报L验证功能Q对于这一点,我们可以使用mx.validators.StringValidator来完成这一功能。应用中q两个参数共同控制按钮的有效性。这样可以在Model对象中设|一个isValid属性,用于l合q两参数?br />
isSymbolValid是一个属性,存放StringValidator的结果?br />在StockMarketPod.mxml中添加mx:StringValidatorq个Tag
从视图中直接调用Model对象不符合MVC原则Q因囑֎则上只能z֏事g。但在这个例子中Q这样已l够好了?/p>
增加格式?br />我们股报价以金额的方式进行展C,在StockMarketPod.mxml中增加一个formatter
现在看一下完整的StockQuotec?br />
其中isPending属性的值由GetStockQuoteCommand控制
最后看一下StockMarketPod.mxml的全部代?br />
此视图中我们不需要用ModelLocatorQ而是使用StockQuote作ؓ参数传入StockMarketPod.mxml
引用视图的代?br />
只传递需要的信息l视图是一个比较好的做法,而尽量少使用ModelLocatorq样的全局变量Q这样也使用视图重用性更高?br />
注意Q视N要传递一些唯一的标识,我们这些标识添加到StockQuotecR?/p>
理对象StockQuoteManagerQ在ModelLocator实例中初始化。但是StockQuoteManager会是一个怎样的对象呢Q?br />通常我用Hashmap来实玎ͼ光值就是视图中的唯一标识W。在构造函C我们可以初始化这个HashmapQFlex2中我们用flash.utils.Dictionary
getStockQuoteҎq回一个stockQuote对象
StockMarketPod.mxml几乎没有什么改动。只需要将那个唯一的标识符发送给命oQ因为命令需要从理对象处取得StockQuote对象。所以GetStockQuoteEventcd了一个quoteId属性?br />在GetStockQuoteCommand中,需要将唯一标识W保存在一个成员变量中
注意一下,在上面的代码中我们用的是无状态命令,在Cairngorm的说明中Q无状态命令是每次Cairngorm事g的响应都创徏一个新的命令实例的方式。因此,在这U方式中我们可以攑ֿ地把变量存储在成员变量中Q而不用担心被其他人改变?br />
相应的脚本代码:
GetStockQuoteCommand响应q处理这个Cairngorm事gQ请求一个业务代理类来报仗?br />
在实际情况中Q需要进行一个远E的服务器端的调用,在Demo中,为简化v见,我注释掉了远E调用的相关代码。这里StockMarketDelegate.as只是对命令进行回调?br />
我们的StockMarketPod视图只需要两条消息,
1. 股票的报?br />2. 错误消息
因ؓ现在是第一ơP代过E中Q处理比较简单,因此使用ModelLocator的成员来解决?br />
在此Demo中,GetStockQuoteCommand命o模拟q回相应的结果?br />
StockMarketPod视图l定q些成员q进行一些格式化的处理?br />
格式化函数的脚本
现在我们来进行重构ƈ一些功能从视图中抽取出来到一个可以进行单元测试的工具cM?/p>
W二ơP代,创徏W合需求的业务逻辑
现在我们已经有一个可以运行的最单的应用。当你的应用变得庞大后,会有很多的限制。你会发C的ModelLocator非常的臃肿,以致于有时候,你都找不C所要的成员。甚至会有命名冲H的事情发生?br />一个普通的重构Ҏ是封装你的用例图中的成员成ؓ一个业务对象。这个业务对象能够表达业务上下文中需要的视图信息。你可以把业务对象设计得最适合用例囄_度。在一个大型的应用中,你可能会设计一pd的业务对象来表达你的用例。你的视囑ְ会绑定这些对象或者这些对象的属性上。通过q种ҎQModelLocator与其目标之间的联pLҎQ开发者更Ҏ掌握业务逻辑所包含的内宏V?br />在这个Demo中,我们可以把astStockQuote和stockQuoteErrorq两个成员封装到一个业务对象中?br />
q样在ModelLocator中,我们只需要定义一个成?br />public var stockQuote : StockQuote = new StockQuote ();
我们的视图也相应修改为:
我们看一个添加商品到购物车的例子. 当应用广?font face="新宋?>ShopController.EVENT_ADD_PRODUCT_TO_SHOPPING_CART命o?
前台控制中下面这行代码保证AddProductToShoppingCartCommand的execute()Ҏ被调?
addCommand( ShopController.EVENT_ADD_PRODUCT_TO_SHOPPING_CART, new AddProductToShoppingCartCommand() );
ShopControllerl承了Cairngorm中的FrontController基类, 因此可以使用addCommand()来给事g注册相应的命?
Cairngorm底层架构完成了剩余部分的工作. 应用中Q意地方简单地q播适当的事? Cairngorm保相应的命令被触发.
另外需要做的是在Mxml的主入口点创建控制器. 在Cairngorm商店? 是Main.mxml, 代码如下:
<control:ShopController id="controller" />
Macromedia Acquires iteration::two in creation of Macromedia Consulting Europe.
Macromedia acquires iteration::two, an industry-leading software consultancy, to create a European Rich Internet Application consulting organisation based in Edinburgh , Scotland.
Cairngorm是Iteration::two的开源项目之一。下载和更新地址?A >http://www.iterationtwo.com/open_source_cairngorm.html
好,现在l箋开始我的学习笔讎ͼ
1. 在Control中有Command.as定义了Command接口Q笔C中FrontController中addCommand的调用添加的Command都必d现此接口。Command接口只定义一个唯一的需要实现的Ҏexecute(); q是一个典型的命o模式, 所有后l的命o都实现此接口, 对外l一提供一个单点入口execute(), 其他的h都可以进行调?但不需要了解命令具体的实现方式.
2. 在Model中定义了ModelLocator接口QModalLocator是所有数据绑定的接口Q也是说应用中所有需要进行绑定的数据都需要通过此接口进行定位。在实际的应用中需要实现此接口Qƈ提供所有的l定数据?BR>
3. 在business中定义了两个c?ServiceLocator和Responder?BR>ServiceLocatorq是伪单例类, 应用开发者用于定义ƈ获得服务.
之所以是伪单例类, 是因为ServiceLocator是定义在mxml中的,
它需要一个无参数的Public构造函? 使用中必d义一个ServiceLocator的子c? q在其中定义需要的服务.
代码CZ:首先在Services.mxml中进行如下定?
在Flexd用中d一行:
<business:Services id="services" />
其中business命名I间在应用头部进行申?BR> xmlns:business="org.nevis.cairngorm.samples.store.business.*"
ServiceLocator使用ҎQ?BR>在业务代理类(Delegate)中通过如下方式q行调用:
* var service = ServiceLocator.getInstance().getService( "customerDelegate" );
在View中,定义了两个类 ViewLocator和ViewHelper
ViewHelper:用于隔离Command命ocdView视图的具体实?
Z执行业务功能, Commandc需要查询ƈ更改视图,
在执行业务逻辑? 命oc需要从视图中获得用戯入的数据;
业务逻辑l束后又l常需要更改视? 昄执行l果.
通过查询和更改视图的操作封装到单独ViewHelpercM, 命ocd全不需要了解视囄的Q何信?
ViewHelper属于一U特D的视图, 当ViewHelper创徏? p注册到指定的视图.
ViewHelperl承自MXMLObject, 在重写的初始化函?initialized)? 调用ViewLocatorq行注册,
q指定unloadҎ的监听函数unregister, 在unload? 调用unregister, 使用ViewLocator的取消注?
ViewLocator是一个单例类, 用于获取ViewHelper操作视图.
命oc需要通过ViewHelper的方法来查询更改视图, 而ViewLocator即用于让命ocd得需要的ViewHelper.
命ocM需要知道ViewHelper的名U? ViewLocator会返回需要的ViewHelper实例.
现在Cairngorm的基框架已经介绍完毕Q将在以后l介l如何在实际应用中用上面提及的基础框架?BR>
我们从Control说v:
在Control? 定义?个基c? Event, EventBroadcaster, FrontController.
Event用于在应用不同的层之间传递事? q携带事件的数据. 包含type和data两个成员.
type存放一个区别不同事件的名称,会在FrontController中进行注?
而在命o(Command)cM, 会对事gq行响应.
EventBroadcaster是一个单例类(singleton), 用于q播用户动作对应的事? 使用Ҏ: EventBroadcaster.getInstance().broadcastEvent( ... )
FrontControllerE微复杂一点点. 用于特定的用户动作分发到指定的命oc?
FrontConroller是请求处理的核心c? 整个体系中遍布的EventBroadcaster.getInstance().broadcastEvent( ... )q样的调?
都是用来通知监听控制? 用户发出了请? 在实际应用中, 开发者应该生成一个FrontContoller的子c?
q在构造函C调用addCommand()注册预期事g的处理命? FrontController的具体实现类应该创徏一ơ而且只能创徏一?
通常的做法是q样? 在主应用? FrontController的子cMZ个Tagq行x,
* <p>
* <code>
* <mx:Application xmlns:control="com.domain.project.control.LoginController" ... >
*
* <control:LoginController id="controller" />
*
* ...
*
* </code>
* </p>
FrontController的处理实质上是这L, 在调用addCommamd? 处理命令保存在数组? 与之对应的事g处理对象注册为FrontController本n,
在事件触? 调用FrontController的handleEvent? 调用executeCommand, 在executeCommand? 先在数组查找Z件对应的命o,
调用命o的executeҎ. q就要求所有的命o都实现Command接口
(内容较多, 未完待箋)