【ArchSummit】如何通过AIOps推动可量化的业务价值增长和效率提升?>>> 了解详情
写点什么

Robotlegs 简介——第 1 部分:上下文与仲裁器

  • 2011-07-28
  • 本文字数:5981 字

    阅读完需:约 20 分钟

要求

预备知识

您应该熟悉 ActionScript 3 和面向对象的术语与准则。此框架的相关经验将有所帮助,但这并非必要条件。

用户级别

中级

必需的产品

如今,在 ActionScript 3 开发框架方面,我们有着诸多选择。这是一种好现象。开源社区生机勃勃,简化开发工作的工具得到积极采用。大型媒体企业、独立游戏开发人员、新手和所有规模的企业都在利用这些工具。

这是 Robotlegs 系列文章的第一部分,后续文章将详述核心 Robotlegs 概念,并介绍一些涉及为与之交互而构建的第三方实用工具和库的更为高级的概念。

什么是 Robotlegs?

简单地来说,Robotlegs 就是一种将对象连接在一起的机制。ObjectA 需要与 ObjectB 通信。ObjectA 不希望或者不需要了解 ObjectB 是否存在。那么它们应该如何通信?最简单的答案就是通过事件实现。利用 Flash,我们拥有一种本机事件系统,专门促进这种类型的通信。就像您在日常工作中使用事件一样,显示列表中的对象会通过事件通信,事件冒泡允许远程对象接收来自其他显示对象的消息。那么未处于显示列表中的对象又会如何?在这种情况下,Robotlegs 这样的框架能够真正地使您的工作更加轻松。

实际上,Robotlegs 就是一组模块化的实用工具和接口,提供的工具可简化这些通信任务、减少重复性的编码任务,同时管理应用程序内的依赖性注入。除了这组核心工具集之外,Robotlegs 还提供了一种略有描述性的 MVC+S(模型、视图、控制器和服务)实现,以便帮助您起步。如果您有过任何 PureMVC 方面的经验,那么就能够迅速适应 Robotlegs MVC+S 实现中的仲裁器与命令的使用,如果您没有这方面的经验也不必担心,我们将在不久之后更加具体地介绍这些类。

这篇文章将利用一个简单的“Hello World”示例,简单介绍 Robotlegs。看到示例之后,您很可能会说:“我完全可以在一个 MXML 文件中完成这一切,而且完全不必这么麻烦!”对于这样一个简单的示例来说,这种说法可能是正确,但不要忘记,在大型项目中,这种结构很快就会体现出自身的价值。这是使用框架开发带来的整体优势。它允许我们有效地沟通概念并理解代码基础,比毫无模式和实践可言的简单堆砌的应用程序更加快捷。

本文不会事无巨细地介绍 Robotlegs 的方方面面,但希望能够激发您的兴趣。我在文章末尾处提供了一些资源,供您进一步探究。闲话到此为止,让我们来看看代码!

Robotlegs MVC+S 应用程序的基本结构

典型的 Robotlegs MVC+S 应用程序由几个部分组成:

  • 上下文是发起依赖性注入和 Robotlegs 使用的各种核心实用工具的引导机制。
  • 仲裁器管理应用程序视图组件与应用程序内其他对象之间的通信。
  • 命令表示应用程序可以执行的各项操作。这些操作通常是为了响应用户活动,但不仅限于此用例。
  • 模型存储数据,并表示应用程序的当前状态。
  • 服务是您的应用程序通往外部世界的门户。

让我们来更加具体地探讨一下上下文和仲裁器,首先从上下文开始。

上下文是应用程序的核心。它提供了中央事件总线,供您的其他应用程序对象用于彼此通信。除了初始加载和引导应用程序之外,您在正常开发过程中不会用到上下文。它会适时出现、完成自己的工作,随后悄然离开,不妨碍您全心投入开发工作。上下文并不是单一的。您的应用程序可有任意多个上下文,这使得 Robotlegs 极为适合模块化的应用程序。本文不会探讨模块化应用程序,但它将作为未来文章的主题,因为这是一种极为强大的工具。作为开始,让我们来观察最基本的上下文。

HelloWorldContext.as

复制代码
import org.robotlegs.mvcs.Context
public class HelloWorldContext extends Context
{
override public function startup():void
{
//bootstrap here
}
}

在上下文内,您覆盖了 startup 方法。startup() 方法是在上下文完全初始化之后调用的。在幕后,调用 startup() 之前,上下文将创建所有核心 Robotlegs 实用工具的实例,准备接收依赖性输入映射,并创建用于在应用程序的多个对象间通信的事件分发器。

创建了 Context 类之后,您的应用程序就需要引用它。在 Flex 4 Spark 应用程序中,这通常是在扩展应用程序的主 MXML 文件内完成的,如下所示。

HelloWorld.mxml

复制代码
<?xml version="1.0"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:local="*">
<fx:Declarations>
<local:HelloWorldContext contextView="{this}"/>
</fx:Declarations>
</s:Application>

由于 Context 属于非可视类,因此必须放置在 Declarations 标签中,您还应该注意,contextView 属性与应用程序本身绑定。上下文视图是 Context 的根视图,并且用于提供自动帮助,用于查看组件仲裁。稍后在讨论视图与仲裁器之间的关系时,我们将介绍相关内容。

这就是上下文。正如我之前提到的那样,它在应用程序的生命周期内仅仅是暂短存在,但又有着至关重要的地位。在上下文就绪之后,我们就可以添加一些视图组件,并使之通过 Robotlegs 彼此通信。让我们来看看仲裁器及其与应用程序视图组件的关系。

仲裁器位于视图组件与应用程序的其他部分之间。简单地来说,仲裁器侦听事件。在用户与组件交互时,或者在组件通过其他某种方式更新时,您的视图组件将分发事件。必须捕捉到这些事件,并将其交付给应用程序的其他部分。或许用户单击了一个 Save 按钮,因此有一些信息需要发送到服务器。仲裁器侦听此事件的发生,在确实侦听到此事件时,仲裁器将收集恰当的信息,并发送一个事件,应用程序的其他部分可以利用此事件来执行某些数据工作单元。

类似地,仲裁器也会侦听来自应用程序其他部分的事件。如果接收到了来自服务器的某些数据,并且进行了解析,服务类也分发了一个事件,则仲裁器的角色就是帮助您侦听此事件,并使用新数据更新视图组件。这里是一个将接收仲裁器的视图。

MessageView.mxml

复制代码
<?xml version="1.0"?>
<s:TextArea
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
</s:TextArea>

这个类非常简短。这仅仅是 TextArea 的一个简单的扩展。为什么不直接使用 TextArea?依赖性注入与明确的类配合得更好。这意味着,通过将 TextArea 扩展到我们的全新 MessageView 类之中,我们就创建了一个特定的视图组件,依赖性注入将据以操作。如果应用程序将有多个不同用途的 TextArea,那么这一点尤为重要。通过按照这种方式划分类,我们就能明确定义类的意图,并允许依赖性注入工具有效地完成自己的工作。对于 MessageView,我们也会在未来添加其他一些功能。就本例而言,它将仍然是一个 TextArea,但您应该了解这一点。现在,我们将观察 MessageView 组件的仲裁器。

MessageViewMediator.as

复制代码
import org.robotlegs.mvcs.Mediator;
public class MessageViewMediator extends Mediator
{
[Inject]
public var view:MessageView;
override public function onRegister():void
{
trace("I am registered!");
}
}

此时,MessageViewMediator 有两个有趣的特性。您很快就会注意到使用 [Inject] 元数据标签的第一处。Robotlegs 使用这个标签来识别需要为之执行注入的属性和方法。使用仲裁器时,只要创建了仲裁器,仲裁后的视图就始终可以注入。您不需要为注入而对视图的映射做出任何特殊考虑。在将视图映射到其仲裁器时,它将为您处理这些问题。稍后我们将介绍相关内容,但首先让我们来看看基本仲裁器的第二个有趣的特性,也就是 onRegister() 方法。

onRegister() 方法是在仲裁器完全初始化时为您提供的一个挂钩。注入已经发生、视图已经就绪,通常您将在这里为视图组件和应用程序添加事件侦听器。您通常要在所创建的每一个 Robotlegs 仲裁器中覆盖此方法。

现在,您已经有了一个视图组件和一个仲裁器,它们需要向上下文注册或者与之映射。这是通过 MediatorMap 实现的。正如其名称所暗示的那样,MediatorMap 是一种在上下文内将仲裁器映射到视图组件的实用工具。此外,MediatorMap 默认侦听 contextView 中的 ADDED_TO_STAGE 和 REMOVED_FROM_STAGE 事件,以便在显示列表中添加或删除视图组件时自动创建和销毁对应的仲裁器。在拥有大量(数以千计)显示对象的图形密集型应用程序中,这并无价值,而且这种自动仲裁可能会导致性能问题。在普通应用程序中,这样的自动化则非常便捷,很少会导致性能问题。我们在 HelloWorldContext 内将 MessageView 映射到其 MessageViewMediator 的方法如下。

复制代码
override public function startup():void
{
mediatorMap.mapView(MessageView, MessageViewMediator);
}

完成这个任务之后,仅剩的工作就是将 MessageView 添加到 HelloWorld.mxml 中。

HelloWorld.mxml

复制代码
<?xml version="1.0"?>
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:local="*">
<fx:Declarations>
<local:HelloWorldContext contextView="{this}"/>
</fx:Declarations>
<local:MessageView top="40" width="100%" height="100%"/>
</s:Application>

现在,在调试器中运行您的应用程序时,您将看到控制台上打印了“I am registered!”祝贺您,您已经得到了一个功能完整的 Robotlegs 应用程序。当然,它现在几乎没有任何实际功能,但我们可以改变这种情况。除了单纯的引导之外,为了给我们的应用程序提供其他一些功能,我们将添加一个名为 HelloButton 的按钮,它扩展了 Spark Button 类,另外还会为 HelloButton 添加一个名为 HelloButtonMediator 的仲裁器。

HelloButton.mxml

复制代码
<?xml version="1.0"?>
<s:Button
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
</s:Button>

HelloButtonMediator.as

复制代码
import flash.events.MouseEvent;
import org.robotlegs.mvcs.Mediator;
public class HelloButtonMediator extends Mediator
{
[Inject]
public var view:HelloButton;
override public function onRegister():void
{
}
}

现在,HelloButtonMediator 看起来与上面的 MessageViewMediator 几乎相同,唯一的差别只有类是不同的。在为 HelloButton 及其仲裁器添加了映射之后,您的上下文启动方法将与此类似。

复制代码
override public function startup():void
{
mediatorMap.mapView(MessageView, MessageViewMediator);
mediatorMap.mapView(HelloButton, HelloButtonMediator);
}

您还要为 HelloWorld.mxml 添加按钮,使之能够添加到显示列表中。您可能还要为 HelloButton 标签属性添加一些有趣的内容,但我将这项任务留给您自行完成。

HelloWorld.mxml

复制代码
<?xml version="1.0"?>
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:local="*">
<fx:Declarations>
<local:HelloWorldContext contextView="{this}"/>
</fx:Declarations>
<local:HelloButton label="Say Hello"/>
<local:MessageView top="40" width="100%" height="100%"/>
</s:Application>

此时,我们就得到了两个完全经过仲裁、急于彼此通信的视图组件。我不是那种会拒绝满足对象的需要的人,因此让我们来完成这个任务——首先从用于通信的自定义事件开始。

HelloWorldMessageEvent.as

复制代码
public function get message():String
{
return _message;
}
public function HelloWorldMessageEvent(type:String, message:String, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
_message = message;
}
override public function clone():Event
{
return new HelloWorldMessageEvent(type, message, bubbles, cancelable)
}

这是一个简单的自定义事件。务必在您的自定义事件中覆盖 clone() 方法。如果没有这个方法,事件就无法重新分发、中继或冒泡。我养成了始终在所有自定义事件中覆盖 clone() 的习惯。如果经历过数个小时艰难的调试,那么您也必然会养成这样的习惯。

我们希望在用户单击 HelloButton 时更新 MessageView。HelloButtonMediator 需要侦听 HelloButton 的 MouseEvent.CLICK 事件,随后将 HelloWorldMessageEvent 分发给应用程序。它并不了解谁会响应这个事件。它也不关心谁会响应这个事件。HelloButtonMediator 只会完成自己的工作。

HelloButtonMediator.as

复制代码
public class HelloButtonMediator extends Mediator
{
[Inject]
public var view:HelloButton;
override public function onRegister():void
{
addViewListener(MouseEvent.CLICK, handleMouseClick)
}
private function handleMouseClick(event:MouseEvent):void
{
dispatch(new HelloWorldMessageEvent(HelloWorldMessageEvent.MESSAGE_DISPATCHED, "Hello World"));
}
}

为 HelloButtonMediator 添加了视图侦听器之后,我们即可将一个事件分发给应用程序。下一步是对这个事件采取一些操作。MessageViewMediator 应该是合乎逻辑的选择。

MessageViewMediator.as

复制代码
public class MessageViewMediator extends Mediator
{
[Inject]
public var view:MessageView;
override public function onRegister():void
{
addContextListener(HelloWorldMessageEvent.MESSAGE_DISPATCHED, handleMessage)
}
private function handleMessage(event:HelloWorldMessageEvent):void
{
view.text = event.message;
}
}

这样,我们就得到了 Hello World!这似乎是一个漫长的过程,但对您的重要应用程序来说,所付出的这些努力一定是值得的。在本系列的下一部分中,我们将探索模型和命令,随后的一篇文章将介绍服务。除了 Robotlegs 的核心之外,我们还会详细探讨目前可用的一些实用工具,以便利用 AS3-Signals 和模块化应用程序开发等工具。使用 Robotlegs 进行开发是一个令人愉悦的过程。

我的博客中有一些关于各种 Robotlegs 主题的文章(互联网上也有其他许多此类文章)。John Lindquist 在他的博客上发表了一个 Hello World 截屏视频(观看他使用 FDT 非常有趣)。除此之外,这篇最佳实践文档已经证明了自身对于许多人的有用价值。您总是可以访问 Robotlegs 知识库来寻求帮助和支持。它拥有一支活跃的社区志愿者队伍,我本人也是其中的一员,我们非常乐于回答与 Robotlegs 有关的所有问题。有关这些主题的深入讨论以及更多内容,请参见面向 ActionScript 开发人员的 Robotlegs 指南

敬请关注本系列的第 2 部分:模块。

clip_image002[4]

本文遵守知识共享—署名- 非商业性使用- 相同方式共享3.0 Unported License (Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License) 许可条件。

原文链接 Introduction to Robotlegs – Part 1: Context and mediators

2011-07-28 22:051347

评论

发布
暂无评论
发现更多内容

count(*)查询性能很差?用这5招轻松优化

小小怪下士

Java 程序员 后端

阿里云产品经理刘宇:Serverless 的前世今生

云布道师

阿里云 Serverless 云原生

最佳实践 | 用腾讯云AI人像变换给自己一次“跨越年龄的体验”

牵着蜗牛去散步

人工智能 腾讯云 腾讯 腾讯云AI

软件测试 | 测试人员必须掌握的测试用例

测试人

软件测试 自动化测试 测试开发 测试用例

聊聊Vuex原理

yyds2026

Vue

PLC与SCADA的什么区别和联系

2D3D前端可视化开发

物联网 PLC 工业控制 web组态 SCADA

彻底搞懂Vue虚拟Dom和diff算法

yyds2026

Vue

OceanBase 首席科学家阳振坤博士入选2022 年度“CCF王选奖”

OceanBase 数据库

6个步骤强化 CI/CD 安全

SEAL安全

HummerRisk V0.5.1 发布:新增对象存储、优化K8s 资源态势和资源拓扑等

HummerCloud

Kubernetes 云原生 云安全 云原生安全

SREWorks v1.3 版本发布 | 插件机制发布

阿里云大数据AI技术

大数据 运维 插件

技术界中的虚拟机、容器和沙箱的关系

FinFish

容器 虚拟机 安全沙箱

Paddle Graph Learning (PGL)图学习之图游走类node2vec模型[系列四]

汀丶人工智能

图神经网络 11月月更

测试大咖漫谈如何搞定软件质量?

测吧(北京)科技有限公司

软件测试

火山引擎 DataTester 首推A/B实验经验库,帮助企业高效优化实验设计能力

字节跳动数据平台

大数据 A/B测试

计算机网络:以太网与IEEE 802.3

timerring

计算机网络 11月月更

查看、校验、归档…带你掌握openGauss账本数据库

华为云开发者联盟

数据库 后端 华为云

Dive into TensorFlow系列(2)- 解析TF核心抽象op算子

京东科技开发者

tensorflow TF2 Tensor Op

使用EasyCV Mask2Former轻松实现图像分割

阿里云大数据AI技术

深度学习 计算机视觉 图像处理 图像分割 企业号十月 PK 榜

【LeetCode】字符串相加Java题解

Albert

算法 LeetCode 11月月更

多视角碰撞,探索 Serverless 企业落地更多可能性丨阿里云用户组厦门站

云布道师

阿里云 云原生

使用SQL加密函数实现数据列的加解密

华为云开发者联盟

大数据 后端 华为云 数据加密

使用 SAP Cloud Application Programming 编程模型开发一个图书管理 OData 服务

Jerry Wang

云原生 CAP SAP 企业级应用 11月月更

带你了解S12直播中的“黑科技”

华为云开发者联盟

云计算 后端 音视频 华为云 实时直播

华为云Astro的前世今生:用7年时间革新低代码开发观念

华为云开发者联盟

低代码 华为云

实时云渲染vs本地渲染,哪个更好用?

Finovy Cloud

云渲染 实时云渲染

浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期

OpenAnolis小助手

Linux 系统运维 内核 龙蜥大讲堂 浪潮

vue的几个提效技巧

yyds2026

Vue

数据库独角兽SingleStore:没有HTAP,机器学习和人工智能都是不切实际的

StoneDB

数据库 开源 HTAP StoneDB SingleStore

OKR之剑·实战篇03:OKR的跟踪需要有“自己”的节奏

vivo互联网技术

团队管理 OKR 目标管理

[力扣] 剑指 Offer 第二天 - 从尾到头打印链表

陈明勇

Go 数据结构与算法 力扣 11月月更

Robotlegs简介——第 1 部分:上下文与仲裁器_Java_Joel Hooks_InfoQ精选文章