Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3355023
  • 博文数量: 530
  • 博客积分: 13360
  • 博客等级: 上将
  • 技术积分: 5473
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-13 13:32
文章分类

全部博文(530)

文章存档

2017年(1)

2015年(2)

2013年(24)

2012年(20)

2011年(97)

2010年(240)

2009年(117)

2008年(12)

2007年(8)

2006年(9)

分类:

2010-05-19 17:05:43

9 Building MVC Architectures

    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架构模式为基础的应用程序。在这一章中,我们将提供关于如何在这种情况下使用的消息框架的一些例子。

9.1 MVC事件流实例(MVC Event Flow Example)

    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:

对于图的步骤解释如下:

  • 1:用户点击"Add to cart"按钮。这将产生一个低层次的UI事件。组件内的事件处理器调用表示层model实例中的一个方法(通常被注入到视图中),用来处理视图与控制器之间的通信。
  • 2:model产生一个系统级的消息(封装了从视图中收集的多种信息),这个消息将通过ParsleysMessageRouter派发;
  • 3:MessageRouter将对所有MXML,XML文件中的 MessageHandlers, MessageBindings, MessageInterceptors 或 Commands进行匹配,本例中,AddToCartCommand被调用。
  • 4:命令将调用远程服务方法(该服务将被注入),异步操作由parsley框架管理。没有一个命令也没有任何应用程序部分必须明确添加结果处理器去接收AsyncToken返回的远程调用结果。
  • 5:框架接收了结果。首先返回命令实例,包含有结果处理器。
  • 6:命令中的结果处理器在将model传递给其它结果处理器之前,可以修改和缓存model
  • 7:框架调用注册的其它结果处理器,本例中CartPM包含一个结果处理器,通过model实例更新内部状态。
  • 8:通过与表示层的model绑定,将视图进行刷新。
  • 1: The user clicks the "Add to cart" button. With Flex for example this will generate a low level UI event. The event handler in the component invokes a method on the presentation model instance (usually injected into the view) which handles communication between View and Controller.
  • 2: The model creates an application message possibly gathering any further information from the view and encapsulating this information in the message. This message will then be dispatched through Parsleys MessageRouter
  • 3: The 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.
  • 4: The command will invoke a remote service method (the service usually being injected). The asynchronous operation will be managed by the framework which allows to avoid some of the usual plumbing code. Neither the command nor any other part of the application has to explicitly add a result handler to the AsyncToken returned by the remote call.
  • 5: The framework receives the result. It is first returned to the command instance itself if it contains a result handler. But this is purely optional.
  • 6: The result handler in the command might modify or cache the model before it gets passed to other result handlers.
  • 7: Next the framework will invoke any other registered result handlers in the application. In this case the CartPM contains a result handler which will now be invoked causing the model instance to update its internal state.
  • 8: The view is refreshed, usually through binding to properties of the presentation model.

    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。


9.2 命令执行例子(Example Command Implementation)

    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.

    我们遵守常规命名习惯,这样可以避免任何元数据配置。框架也可以知道哪个方法执行命令,哪个处理结果或错误。结果和错误处理器是可选的。


阅读(2079) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

chinaunix网友2010-11-21 19:37:21

会的不用看,不会的看不懂