分类:
2010-05-19 17:05:43
Parsley is different from several other Flex or Flash MVC Frameworks in that it does not provide very much explicit support for the various pieces of an MVC architecture. This was a side effect of our primary goal being to allow to design a fully decoupled architecture. Decoupled in a sense that not only the parts of your application are decoupled from each other, but also decoupled from the framework itself. For example providing base classes for controllers or mediators in the framework that application classes have to extend is a bad idea if you want to support such a decoupled architecture.
parsley与几个其他Flex或Flash的MVC框架的不同,它没有提供一个非常明确的MVC架构。这是为了设计出完全分离的架构目标的副作用。解耦不仅是您的应用程序部分是彼此分离,而且与框架分离。对于提供了控制器或mediators 的框架,如果你想支持这种分离的架构,应用程序的类必须扩展基类的例子是一个坏主意。
For that reason the Messaging Framework in Parsley which we already described in is pretty generic. It does not assume a particular programming style or architectural pattern. Nevertheless Parsley still falls into the same category as many other MVC Frameworks since the Messaging Framework can easily be used in a way that helps building an application based on the MVC architectural pattern. In this chapter we will provide some examples on how to use the Messaging Framework in such a context.
出于这个原因,在parsley消息框架,我们已经在
描述过了。它并不是一个编程风格和框架模式。虽然parsley与许多其他MVC框架属于同一范畴,但消息框架可以很容易地帮助建立基于MVC架构模式为基础的应用程序。在这一章中,我们将提供关于如何在这种情况下使用的消息框架的一些例子。
The following diagram shows an example flow for a particular use case (user adds item to shopping cart) in the context of a Parsley MVC application:
下图显示了一个在parsley MVC 系统的特殊应用例子(添加货物到购物车内)。
Explanations for the numbered steps from the diagram:
对于图的步骤解释如下:
的
MessageRouter派发;
MessageRouter将对所有MXML,XML文件中的
MessageHandlers, MessageBindings, MessageInterceptors 或 Commands进行匹配,本例中,AddToCartCommand
被调用。MessageRouter
MessageRouter
will then process any MessageHandlers, MessageBindings, MessageInterceptors
or Commands which were registered for this message type (usually with Metadata tags on methods or properties, alternatively
in MXML or XML). In this case the AddToCartCommand
will be invoked. From the example above many core elements will have been setup and wired in a
Parsley Context
including the view as described in .
This usually includes all controller actions, their dependencies like remote services,
and the registration for particular messages in the MessageRouter
.
从本例中,一些核心元素将建立和注入到parsley上下文中,包括。这通常包括所有控制行为,远程服务和MessageRouter中的消息注册。
If you think this diagram smells like over-engineering, it merely serves as an example for a full blown MVC architecture of a large and complex application. In smaller and simpler applications you can of course simplify the design presented above. For example the Mediator may be omitted in simpler use cases where the view itself dispatches and receives application messages.
这个图仅作为大型复杂MVC框架的一个例子。在小型和简单的系统中,你当然可以简化上面的设计模式。例如,对于小型项目,视图派发和接收系统消息,可以忽略Mediator。
Finally we'll pick one of the pieces presented in the diagram above and show
how the implementation and configuration of such an application part may look like.
We'll chose the AddToCartCommand
that participates in the application flow shown in the diagram.
最后,我们展示系统的配置信息如何执行。我们选择AddToCartCommand:
package com.bookstore.actions {
import mx.rpc.AsyncToken;
import mx.rpc.Fault;
import mx.rpc.remoting.RemoteObject;
import com.bookstore.events.CartEvent;
import com.bookstore.services.CartService;
import com.bookstore.model.LineItem;
public class AddToCartCommand {
[Inject(id="cartService")]
public var cartService:RemoteObject;
public function execute (event:CartEvent) : AsyncToken {
return cartService.addItem(event.item);
}
public function result (item:LineItem) : void {
/* modify or cache the result */
}
public function error (fault:Fault) : void {
/* handle fault */
}
}
}
And this is how you can configure such a command in a Parsley configuration class (in this case MXML):
这里展示一个如何在parsley配置类(比如MXML)中配置这个命令:
type="{AddToCartCommand}"
selector="addItem"/>
We'll now examine the various parts of this class in detail. First there is the method that executes the command:
我们将详细看一下这个类的细节,首先有一个方法执行命令:
public function execute (event:CartEvent) : AsyncToken {
In this example we are using regular Flash Events as application messages, but you are not forced to do so as described in .
这个例子使用flash事件作为应用程序消息,不会迫使你按的做。
The method parameter tells the framework that we are interested
in CartEvents
. MessageHandler selection happens based on message type, so in a large and complex application
you won't run into problems having to maintain event type constants which are unique across the whole system.
这个方法的参数告诉框架,我们对CartEvents感兴趣。
MessageHandler的选择器可以过滤消息类型。因此,对于大型和复杂应用程序,你不会遇到维护事件类型常量,保证惟一性的困难
But since we are not interested in all CartEvents that get dispatched we specify a selector
attribute
in the MXML configuration
which in case of Events points to the type property of the Event. In this case we are intereseted in CartEvents with
the type addItem
which was dispatched by the View or the presentation model as a result of an UI event.
但是,因为我们不是对所有的CartEvents感兴趣,我们在MXML配置信息中描述了一个选择属性。本例中,我们只对CartEvents事件中的addItem
感兴趣。CartEvents事件可以由视图派发或者是一个UI事件的表示层模型作为结果。
In the body of that method we are using the injected CartService
:
对于方法内部,我们注入了CartService:
[Inject(id="cartService")]
public var cartService:RemoteObject;
In this example we are using a RemoteObject. We usually prefer to use injection by type but this is not applicable for RemoteObjects which can only be distinguished by id. For details see .
本例中,我们只使用了一个远程对象。我们通常通过类型注入,通过ID进行注入并不是很好。详细参见。
Finally there are the result and error handlers:
最后,大家看一下result和error处理器:
public function result (item:LineItem) : void {
public function error (fault:Fault) : void {
We are following a naming convention here so we can avoid any metadata configuration altogether. Based on the method names the framework knows which method executes the command and which handles results or faults. The result and error handler are both optional.
我们遵守常规命名习惯,这样可以避免任何元数据配置。框架也可以知道哪个方法执行命令,哪个处理结果或错误。结果和错误处理器是可选的。