常用Flex IOC框架比较分析.docx
- 文档编号:3444991
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:19
- 大小:81.28KB
常用Flex IOC框架比较分析.docx
《常用Flex IOC框架比较分析.docx》由会员分享,可在线阅读,更多相关《常用Flex IOC框架比较分析.docx(19页珍藏版)》请在冰豆网上搜索。
常用FlexIOC框架比较分析
常用FlexIOC框架比较分析
常用FlexIOC框架比较分析
IOC(InversionofControl),也称DI(DependencyInjection),是近年来在软件开发中变得非常流行的一种设计策略。
众多的Flex开发者,探索出了诸如SpringActionScript、Parsley、Flicc和Swiz这样的IOC框架。
什么是IOC?
一言以蔽之,IOC是一种软件设计模式。
借助IOC,可用一个独立的对象为其他对象的数据成员填充正确的实现,而不是由这些对象自己负责此项工作。
这样做的好处有两个。
第一,可将对象的数据成员声明为接口,从而将对象与其具体实现分离(即契约式设计,designbycontract)。
第二,可从对象中删除创建逻辑,可以使对象的用途更为明确。
IOC容器提供一个框架,你可借此以一致和宣告的形式使用这个模式。
将此模式和接口结合起来,可以创建出易于测试、使用灵活的对象。
有关IOC模式更深入的讨论,请参看MartinFowler的文章InversionofControlContainersandtheDependencyInjectionpattern*。
Java和.NET的IOC框架早已建立,在Flex社区,近来也有不小的进展。
本文将讨论Flex中的一些IOC框架的工作原理、使用方法,并对这些框架进行比较。
为了比较方便,我将在同一个工程(ProfileViewer)中使用SpringActionScript、Parsley、Flicc和Swiz这几个框架
IOC的概念
一般有两种最常见的对象配置方法:
∙对象实例化(例如:
myObject=newObject())
∙对象查找(例如:
varmyObject=registry.getMyObject())
而利用IOC,你可在一个独立层中实例化应用程序要用到的对象,并传入它们所需的依赖。
具体来说,最常见的实现方法也有两种:
∙Setter注入(例如:
instance.myObject=newObject())
∙Constructor注入(例如:
instance=newInstance(newObject()))
一个IOC框架,通常由如下三个部分组成:
配置、工厂和注入机制。
配置
我们可以在配置中描述对象之间的关系。
最常用的配置描述方法是在文件中声明。
这样的文件有时候也被称为上下文文件(contextfile)。
也可以用元数据/注释(metadata/annotation),甚至直接在程序中描述配置。
工厂
工厂负责配置的解析和所有对象的准备工作,程序一旦运行,就可以根据需要取得这些对象。
在经典的Spring框架(最流行的JavaIOC框架)中,所有对象(我称其为客户对象)都由IOC容器负责准备,并且它们以接口形式声明自己的依赖。
在配置文件中,被声明的依赖都被设置为对应的实现类。
注入机制
所谓注入机制,是指如何将工厂创建的对象实例注入到应用或其他对象。
就SpringWeb应用而言,注入方法是通过web.xml来实现的。
Spring会监听webapp上下文的加载事件,并利用钩子捕获类加载器的行为,从而分离出任何需被创建的对象。
此后,若有需要,工厂将实例化对象,并填充它所需的依赖。
当然在向应用返回对象之前,这些依赖本身也可能需要实例化。
这个过程即所谓的“(将依赖与对象)捆绑在一起”。
在Flex中,类的加载原理有所不同,因此捆绑方法也就不同。
目前有两种方法:
∙客户对象直接从工厂请求(已捆绑好的)对象
∙利用内置的Flex事件机制(用于实例化视图)触发注入
到后面我们具体讨论框架时,这些概念会更容易理解。
ProfileViewer介绍
ProfileViewer是一个非常简单的应用,只有两个界面(一个登录面板、一个仪表盘),接下来我们就用这个工程比较、讨论四个框架。
ProfileViewer使用了MVC(Model-View-Controller)架构和PresentationModel模式。
说明:
我将ProfileViewer建立自己过去看到的一些较为流行的设计模式基础上,仅仅是一个例子,使用这些框架肯定还有其他使用方法。
如果你觉得我的方法有任何问题,请一定告诉我。
我非常乐意根据大家的意见和建议调整改进。
本文所有例子的源代码可从flex-ioc-examplesproject*下载。
我建议打开这些源码,对照着阅读本文下面的内容时。
高层架构
开发GUI应用时,通常会用到MVC模式。
我们就不在这里深入讨论MVC本身的细节了,如果有需要请参看可参看Model-view-controller*。
在此之上,我实现了服务层(见图1)。
应用可在这里得到来自后端系统的数据。
在本例中,我简化了这个部分的实现。
最后,我使用了PresentationModel模式,应用中每个视图都有对应的模型,模型包含了它的状态和逻辑。
正常情况下,视图通过绑定表达式响应模型的状态变化。
这样,对视图逻辑做单元测试是没有问题的。
有关更多细节,请参看MartinFowler对PresentationModel模式的说明*或PaulWilliams的文章*。
图1.初期架构
架构改进
为把IOC框架引入ProfileViewer,我需将对象实例及其依赖的管理转移到IOC层(见图2)。
一些框架支持将事件关联到Action,藉此可以搭建一个Controller层。
我将在适当的地方使用框架提供的这些功能。
图2.引入IOC后的框架
接下来,我主要说明通过引入IOC,应用中可得到改善的部分。
对象查找
用户登录成功后,应用取回两个对象。
这两个对象包含的信息会在不同的视图中展示给用户。
当准备仪表盘的表现层模型(DashboardPM)时,我需查找这两个对象实例:
在MainPM中:
publicfunctionset
authenticated(value:
Boolean):
void
{
//..
varlocator:
ModelLocator=ModelLocator.getInstance();
dashboardPM=newDashboardPM(locator.user,locator.friends);
//..
}
ModelLocator使用了单例模式*,用于存储模型对象。
依靠单例,我在应用的任何地方得到都是相同的对象实例,因为仅仅创建一个对象实例。
在这种情况下,我可以安全访问User和Friends,因为在任何地方,它们都只有一个实例。
不过,单例也有其不足,比如造成单元测试困难——在测试套件整个存在期内,你都必须关注对象的生命周期。
因为单例独立于测试用例,静态存储而不会被当做垃圾收集。
对象传递
弱化应用中单例负面影响的办法之一,是按类的继承层次传递对象。
你可以在DashboardPM的构造器的实现中看到这一点。
它需取得User和Friends模型,然后由表现层模型将这些实例传递给自己的子类(尽管实际上只会用到User对象)。
一个对象依赖于另一个实际并不直接使用的对象,这显然是一种糟糕的设计实践。
对于小的例子程序而言,这不会是什么大问题,但随着应用规模的扩张,你可以想象这种方法会带来多大的工作量。
它也会给你的类带入本不需要的杂质。
如果你能只实例化需要的对象,代码将变得更为干净。
最初的ProfileViewer的表现层模型被配置成继承结构,利用它可以实现对象的传递;引入IOC后,这个继承结构就不需要了,我会将其删除。
配置服务层
实现非视图层的配置,是对本例的一个有力支持。
在本例中通过LoginDelegate类来表述,这个类会创建它自有的RemoteObject实例。
SpringActionScript
框架:
SpringActionScript
网站:
开发者:
ChristopheHerreman
版本:
0.71
许可:
开源
配置:
XML
SpringActionScript前身为Prana,因其成熟度高,成为了一个知名框架。
核心概念
任何使用过Spring的Java或.NET版本的人,都会很快熟悉SpringActionScript。
你在运行时加载的配置文件,可以给工厂提供足够信息,用于实例化被应用请求的任何对象。
基本配置
在标准例子工程中使用SpringActionScript,需如下三个基本步骤:
1创建文件application-context.xml
2初始化应用中的工厂对象
3在你的视图层(或其他任何地方),根据需要从工厂获得对象以供使用
对象工厂和对象配置
在SpringActionScript中,对象声明在应用可访问的XML文件(通常命名为application-context.xml)中。
此配置文件由XMLApplicationContext(是ObjectFactory的子类)加载。
在本例中,初始化工作由如下两个对象承担:
ContextLoader和Inject。
ContextLoader获得应用上下文文件的路径。
该文件在XMLApplicationContext中加载。
在应用初始化部分有:
privatefunctioninit():
void
{
ContextLoader.contextPath="application-context.xml";
}
ContextLoader在幕后实现对SpringActionScript上下文的加载:
publicstaticfunctionsetcontextPath(value:
String):
void
{
_contextPath=value;
applicationContext=newXMLApplicationContext(_contextPath);
applicationContext.addEventListener(Event.COMPLETE,handleLoadComplete);
applicationContext.load();
}
接着在需要依赖的视图中,我创建一个Inject标签(受一个同事在Parsley中实现的启发)。
利用这个标签,我可以很方便的声明我需将何种依赖添加到该视图。
例如,在应用启动时,我有如下代码:
Inject property="pm" objectId="{ContextIds.MAIN_CONTAINER_PM}"/> Inject property="controller" objectId="{ContextIds.CONTROLLER}"/> 这将向XMLApplicationContext请求一个ID为CONTROLLER的对象,并将它赋给视图中的成员变量controller。 这是在视图层获取对象的好办法。 说明: ChristopheHerreman曾撰文*说明如何用metadata实现上述类型的注入(类似Swiz框架),但这种方法有性能问题,因为要读取元数据,视图需序列化为XML。 设置控制器 SpringActionScript已计划发布一个支持MVCS的的扩展版*。 但在目前版本中,我将实现一个自有的控制器,并利用SpringActionScript将处理程序挂接到事件源。 在最初的程序中,控制器会监听所有事件。 当它截获到一个事件后,会查找所有处理器,筛选出能处理这个事件的对象。 在经过修改后的例子中,不再监控整个显示列表,转而在application-context.xml中将事件源和事件处理器配对。 为此,我增加了一个新类ControllerPair,它负责事件源和处理器的配对。 所有对被传递给SimpleController,并在它的init()函数中初始化每个对。 请注意其中的method-invocation标签,我们用它来指定对象被创建后马上自动调用的函数。 在这里,被自动调用的函数是init(),它负责将事件派发者绑定到事件处理器。 N 表现层模型的注入 在非IOC版的ProfileViewer中,为了实现对象的传递,表现层模型被配置为继承式结构。 在IOC版中,我将删除此结构,以便每个表现层模型都能被配置为对应的视图。 尽管这样做,应用更易于配置和测试,但也有其缺点。 在某些情况下,要实现离散的表现层模型之间的交互,需要做不少工作。 SpringActionScript同时支持setter和constructor两种形式的注入。 我更倾向于使用construtor注入,因为它可以完全暴露对象运作所需的全部依赖。 如下是DashboardPM的配置: 在XML中声明构造函数的参数时,顺序应和对象的构造函数所期望的参数顺序相同。 上面代码中的ref表示引用在上下文中声明的另一个对象,在这里即User。 配置服务层 LoginHandler引用了代理对象,代理对象又依赖于另一个远程对象,该远程对象可以调用后端系统的功能。 下面,我们用setter完成这些对象的配置。 需通过setter传入的实例包括代理对象和AuthenticationClient(这是一个用于检查用户是否已登录的接口)。 MainPM具体实现了AuthenticationClient。 在这里,我将代理设计为存根,依赖于一个远程对象。 配置如下: 总结 SpringActionScript是一个优秀的、成熟的、开发活动十分活跃的IOC框架。 它使用的术语,应该说是任何用过Spring框架的人都熟悉的。 以XML形式声明对象存在一个问题,即在XML中声明一个类,并且这个类没被包含在SWF中(因为在你的应用中没有对它的直接引用)时,FlashPlayer会在运行时抛出异常。 其解决办法是创建一个ActionScript类,声明它对上下文XML的依赖,并将此类包含在应用中。 Parsley 框架: Parsley 网站: http: //www.spicefactory.org/* 开发者: JensHalm 版本: 2.0.0 许可: 开源 配置: XML/MXML/ActionScript Parsley也是一个成熟的IOC框架,最初灵感来源于Spring。 它近期经历过一次较大规模的重写。 新版本支持一些本地Flex特性,如绑定和元数据,使你在配置你的工程时有更多更好的选择。 核心概念 Parsley的核心概念是源自于Spring的上下文,也即应用的依赖注入的配置。 Parsley的配置现在支持多种形式,其中包括XML和MXML。 你可以使用本地的MXML标记或Parsley库提供的自定义MXML标签。 Parsley使用元数据标签实现对注入机制的支持,这和Swiz框架是类似的。 Parsley还支持消息模式。 基本不需代码干预,你就能将你的对象配置为事件源或事件处理器。 在这个例子中,我会用这个特性替代Controller模式。 基本配置 Parsley的配置分三个基本步骤: 1创建Config.mxml文件。 2在应用的根部初始化一个Context对象。 3在你的视图中,用Inject元数据实现依赖的注入。 准备配置文件的方法有多种,不过在这个例子中,我使用支持本地标记和Parsley标签的MXML文件。 这种方法的好处是在编译时就将类引入,当然这样一来,也就不能直接修改已被编译的应用的配置了。 对象工厂和对象配置 在Config.mxml中,你能看到应用中用到的从域模型到代理的所有对象。 声明这些对象的方式有两种: 4标准的MXML 5使用Parsley的对象定义标签 在后面的内容中,我将详细介绍这种方法。 设置控制器和LoginHandler 我在这里不再使用自己编写的控制器,转而使用Parsley的消息系统(其设计决定了它对你编写的对象的影响很小)。 具体是用元数据来实现。 Parsley将事件源绑定到事件处理器,需要一个在Context可见且具有元数据的对象。 在这个例子应用中,LoginPM是事件源,LoginAction(从LoginHandler重命名而来)是事件处理器。 如下代码摘自LoginPM: [Event(name="LOGIN",type="com.adobe.login.control.event.LoginEvent")] [ManagedEvents("LOGIN")] publicclassLoginPMextendsEventDispatcher { ... publicfunctionlogin(): void { varevent: LoginEvent=newLoginEvent(username,password); dispatchEvent(event); } } 让LoginPM成为事件源需要三个要素: Event元数据标签、ManagedEvents元数据标签,以及EventDispatcher#dispatchEvent。 三者当中,只有ManagedEvents是Parsley扩展而来。 Event元数据仅为习惯做法,事件的实际派发工作是由dispatchEvent完成的。 Parsley将通过ManagedEvents决定它要处理哪个事件,并将该事件委托给事件处理器。 如下代码摘自LoginAction(已经被配置为事件处理器): publicclassLoginActionimplementsIResponder { [MessageHandler] publicfunctionexecute(event: LoginEvent): void { ... } } 因为我为这个函数补充了MessageHandler元数据,Parsley将把这个对象/函数当做类型为LoginEvent的所有事件的监听器。 要让这些对象对Parsley可见,可在传入FlexContextBuilder的配置文件内声明这些对象,或在视图中使用Configure对象。 表现层模型的注入 和其他例子一样,我已将表现层模型的继承结构去除。 相关原因请参看SpringActionScript。 Parsley支持setter和constructor两种注入方法。 像我在SpringActionScript例子中提到的那样,我更倾向于使用constructor注入,因为它可以暴露出对象运作所需的全部依赖。 如是是DashboardPM的配置: Objecttype="{DashboardPM}"/> 如果你的对象构造函数需要参数,则应该用Object标签予以声明,因为这样的参数在本地MXML中是不支持的。 要完成此构造函数,你需向类中添加一些元数据: [InjectConstructor] publicclassDashboardPM { publicvaruser: User; publicfunctionDashboardPM(user: User) { this.user=user; } ... } 这里的元数据标签InjectConstructor,表示要求Parsley给DashboardPM的构造函数注入一个类型为User的、已声明过的对象。 若使用setter注入,你仅需在类中增加元数据标签Inject。 例如,我在Config中用标准MXML声明SummaryPM: SummaryPM/> 接着,在类文件中有如下代码: publicclassSummaryPM { [Inject] publicvarfriends: Friends; ... } 这里的Inject标签表示需将一个类型为Friends的实例注入到SummaryPM。 总结 经过其他一些框架的不断启发,新版本的Parsley已发展成为一个完整的IOC框架。 它还支持模块式开发和上下文卸载。 在模块化Flex应用开发日益盛行的今天,这无疑是一个十分重要的特性。 常用FlexIOC框架比较分析 Flicc 框架: Flicc 网站: 开发者: MikeHerron 版本: 0.5 许可: 开源 配置: MXML 在IOC领域,Flicc是一个不太知名的后来者。 它的配置方法(利用MXML文件)略有不同。 它在MXML中有自己的对象定
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 常用Flex IOC框架比较分析 常用 Flex IOC 框架 比较 分析