Command、Delegate、Service这三者的关系简单说来就是前者调用后者,后者为前者返回数据的关系!
让我们以参考资料中的源码为例详细描述一下:
Command的源代码如下,类名叫:GetProductsCommand
package com.adobe.cairngorm.samples.store.command { import mx.rpc.IResponder; import com.adobe.cairngorm.commands.ICommand; import com.adobe.cairngorm.control.CairngormEvent; import com.adobe.cairngorm.samples.store.business.ProductDelegate; import com.adobe.cairngorm.samples.store.model.ShopModelLocator; import com.adobe.cairngorm.samples.store.util.Comparator; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; import mx.controls.Alert; import mx.collections.ICollectionView; import mx.collections.Sort; import mx.collections.SortField; import mx.utils.ArrayUtil; public class GetProductsCommand implements ICommand, IResponder { public function execute( event : CairngormEvent ): void { if( ShopModelLocator.getInstance().products == null ) { var delegate : ProductDelegate = new ProductDelegate( this ); delegate.getProducts(); } else { Alert.show( "Products already retrieved!" ); return; } } public function result( event : Object ) : void { //result()方法从表现服务器结果的event中提取 //products数组并将它们保存在ShopModelLocator中, //同时将selectedItem设置为产品列表中的第一个产品。 var products : ICollectionView = ICollectionView( event.result ); var model : ShopModelLocator = ShopModelLocator.getInstance(); // sort the data。 var sort :Sort = new Sort(); sort.fields = [ new SortField( "name", true ) ]; products.sort = sort; products.refresh(); // set the products on the model model.selectedItem = products[ 0 ]; model.products = products; model.workflowState = ShopModelLocator.VIEWING_PRODUCTS_IN_THUMBNAILS; } public function fault( event : Object ) : void { var faultEvent : FaultEvent = FaultEvent( event ); Alert.show( "Products could not be retrieved!" ); } } }
注意代码中的这一行:
这里将GetProductsCommand类的实例作为参数(this)传递给ProductDelegate的构造函数,这样做就是告诉Delegate,该Command将处理所有通过Dlegate发送的请求所返回的结果。在Delgate中,这个接收所有返回结果的Delegate成为Responder。如下Delegate的源码(ProductDelegate.as)中可以看到:
package com.adobe.cairngorm.samples.store.business { import mx.rpc.IResponder; import com.adobe.cairngorm.business.ServiceLocator; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.AbstractOperation; public class ProductDelegate { //构造函数的参数为IResponder类,将接受所有请求的返回结果 public function ProductDelegate( responder : IResponder ) { this.service = ServiceLocator.getInstance().getRemoteObject( "productService" ); this.responder = responder; } public function getProducts() : void { //调用Service,这两行代码可以作为模板,在其他Cairngorm应 //用中写法也是一样的!这两行代码确保了从服务器返回的 //results 和faults都能返回给Delegate。 var call : Object = service.getProducts(); call.addResponder( responder ); } private var responder : IResponder; private var service : RemoteObject; } }
从第一段代码中可以看到,Command类实现了ICommand和 IResponder两个接口,当它选择扮演responder的角色,Command实现FLEX定义的IResponder接口;这确保了开发者可以添加一个result()犯法来处理任何
Delegate结果,一个fault()方法来处理所有
Delegate的错误。
整个工作流程可以描述如下:
通过这个机制的运用,一方面使得Delegate可以被重用,另一方面将服务器端调用进行了封装,delegate变成了客户端代码和服务器端代码的唯一接口。这样做也为客户端和服务器端代码分别开发提供了可能(我们在写客户端程序是不一定服务器端程序已经就绪,只需要它提供一些静态试验数据(或称为为数据:dummy data)即可)。