资源预览内容
第1页 / 共17页
第2页 / 共17页
第3页 / 共17页
第4页 / 共17页
第5页 / 共17页
第6页 / 共17页
第7页 / 共17页
第8页 / 共17页
第9页 / 共17页
第10页 / 共17页
亲,该文档总共17页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
常用Flex IOC框架比较分析IOC(Inversion of Control),也称DI(Dependency Injection),是近年来在软件开发中变得非常流行的一种设计策略。众多的Flex开发者,探索出了诸如Spring ActionScript、Parsley、Flicc和Swiz这样的IOC框架。什么是IOC?一言以蔽之,IOC是一种软件设计模式。借助IOC,可用一个独立的对象为其他对象的数据成员填充正确的实现,而不是由这些对象自己负责此项工作。这样做的好处有两个。第一,可将对象的数据成员声明为接口,从而将对象与其具体实现分离(即契约式设计,design by contract)。第二,可从对象中删除创建逻辑,可以使对象的用途更为明确。IOC容器提供一个框架,你可借此以一致和宣告的形式使用这个模式。将此模式和接口结合起来,可以创建出易于测试、使用灵活的对象。有关IOC模式更深入的讨论,请参看Martin Fowler的文章Inversion of Control Containers and the Dependency Injection pattern。Java和.NET的IOC框架早已建立,在Flex社区,近来也有不小的进展。本文将讨论Flex中的一些IOC框架的工作原理、使用方法,并对这些框架进行比较。为了比较方便,我将在同一个工程(ProfileViewer)中使用Spring ActionScript、 Parsley、Flicc和Swiz这几个框架。IOC的概念 一般有两种最常见的对象配置方法: 对象实例化(例如:myObject = new Object() ) 对象查找(例如: var myObject = registry.getMyObject() ) 而利用IOC,你可在一个独立层中实例化应用程序要用到的对象,并传入它们所需的依赖。具体来说,最常见的实现方法也有两种: Setter注入(例如: instance.myObject = new Object() ) Constructor注入(例如: instance = new Instance( new Object() ) ) 一个IOC框架,通常由如下三个部分组成:配置、工厂和注入机制。配置我们可以在配置中描述对象之间的关系。最常用的配置描述方法是在文件中声明。这样的文件有时候也被称为上下文文件(context file)。也可以用元数据/注释(metadata/annotation),甚至直接在程序中描述配置。工厂工厂负责配置的解析和所有对象的准备工作,程序一旦运行,就可以根据需要取得这些对象。在经典的Spring框架(最流行的Java IOC框架)中,所有对象(我称其为客户对象)都由IOC容器负责准备,并且它们以接口形式声明自己的依赖。在配置文件中,被声明的依赖都被设置为对应的实现类。注入机制所谓注入机制,是指如何将工厂创建的对象实例注入到应用或其他对象。就Spring Web应用而言,注入方法是通过web.xml来实现的。Spring会监听webapp上下文的加载事件,并利用钩子捕获类加载器的行为,从而分离出任何需被创建的对象。此后,若有需要,工厂将实例化对象,并填充它所需的依赖。当然在向应用返回对象之前,这些依赖本身也可能需要实例化。这个过程即所谓的 “(将依赖与对象)捆绑在一起”。在Flex中,类的加载原理有所不同,因此捆绑方法也就不同。目前有两种方法: 客户对象直接从工厂请求(已捆绑好的)对象 利用内置的Flex事件机制(用于实例化视图)触发注入 到后面我们具体讨论框架时,这些概念会更容易理解。ProfileViewer介绍 ProfileViewer是一个非常简单的应用,只有两个界面(一个登录面板、一个仪表盘),接下来我们就用这个工程比较、讨论四个框架。 ProfileViewer使用了MVC(Model-View-Controller)架构和Presentation Model模式。说明: 我将ProfileViewer建立自己过去看到的一些较为流行的设计模式基础上,仅仅是一个例子,使用这些框架肯定还有其他使用方法。如果你觉得我的方法有任何问题,请一定告诉我。我非常乐意根据大家的意见和建议调整改进。本文所有例子的源代码可从flex-ioc-examples project下载。我建议打开这些源码,对照着阅读本文下面的内容时。高层架构开发GUI应用时,通常会用到MVC模式。我们就不在这里深入讨论MVC本身的细节了,如果有需要请参看可参看Model-view-controller。在此之上,我实现了服务层 (见图1)。应用可在这里得到来自后端系统的数据。在本例中,我简化了这个部分的实现。最后,我使用了Presentation Model模式,应用中每个视图都有对应的模型,模型包含了它的状态和逻辑。正常情况下,视图通过绑定表达式响应模型的状态变化。这样,对视图逻辑做单元测试是没有问题的。有关更多细节,请参看Martin Fowler对Presentation Model模式的说明或Paul Williams的文章。图1. 初期架构 架构改进为把IOC框架引入ProfileViewer,我需将对象实例及其依赖的管理转移到IOC层(见图2)。一些框架支持将事件关联到Action,藉此可以搭建一个Controller层。我将在适当的地方使用框架提供的这些功能。图2. 引入IOC后的框架 接下来,我主要说明通过引入IOC,应用中可得到改善的部分。对象查找用户登录成功后,应用取回两个对象。这两个对象包含的信息会在不同的视图中展示给用户。当准备仪表盘的表现层模型(DashboardPM)时,我需查找这两个对象实例:在MainPM中:public function setauthenticated( value : Boolean ) : void /. var locator : ModelLocator = ModelLocator.getInstance(); dashboardPM = new DashboardPM( locator.user, locator.friends ); /. ModelLocator使用了单例模式,用于存储模型对象。依靠单例,我在应用的任何地方得到都是相同的对象实例,因为仅仅创建一个对象实例。在这种情况下,我可以安全访问User和Friends,因为在任何地方,它们都只有一个实例。不过,单例也有其不足,比如造成单元测试困难在测试套件整个存在期内,你都必须关注对象的生命周期。因为单例独立于测试用例,静态存储而不会被当做垃圾收集。对象传递弱化应用中单例负面影响的办法之一,是按类的继承层次传递对象。你可以在DashboardPM的构造器的实现中看到这一点。它需取得User和Friends模型,然后由表现层模型将这些实例传递给自己的子类(尽管实际上只会用到User对象)。一个对象依赖于另一个实际并不直接使用的对象,这显然是一种糟糕的设计实践。对于小的例子程序而言,这不会是什么大问题,但随着应用规模的扩张,你可以想象这种方法会带来多大的工作量。它也会给你的类带入本不需要的杂质。如果你能只实例化需要的对象,代码将变得更为干净。最初的ProfileViewer的表现层模型被配置成继承结构,利用它可以实现对象的传递;引入IOC后,这个继承结构就不需要了,我会将其删除。配置服务层实现非视图层的配置,是对本例的一个有力支持。在本例中通过LoginDelegate类来表述,这个类会创建它自有的RemoteObject实例。Spring ActionScript 框架: Spring ActionScript 网站: http:/www.herrodius.com/blog/ 开发者: Christophe Herreman 版本:0.71 许可:开源 配置: XML Spring ActionScript前身为Prana,因其成熟度高,成为了一个知名框架。 核心概念任何使用过Spring的Java或.NET版本的人,都会很快熟悉Spring ActionScript。你在运行时加载的配置文件,可以给工厂提供足够信息,用于实例化被应用请求的任何对象。基本配置在标准例子工程中使用Spring ActionScript,需如下三个基本步骤:1. 创建文件application-context.xml 2. 初始化应用中的工厂对象 3. 在你的视图层(或其他任何地方),根据需要从工厂获得对象以供使用 对象工厂和对象配置在Spring ActionScript中,对象声明在应用可访问的XML文件(通常命名为application-context.xml)中。此配置文件由XMLApplicationContext(是ObjectFactory的子类)加载。在本例中,初始化工作由如下两个对象承担:ContextLoader和Inject。ContextLoader获得应用上下文文件的路径。该文件在XMLApplicationContext中加载。在应用初始化部分有:private function init() : void ContextLoader.contextPath = application-context.xml; ContextLoader在幕后实现对Spring ActionScript上下文的加载:public static function set contextPath( value : String ) : void _contextPath = value; applicationContext = new XMLApplicationContext( _contextPath ); applicationContext.addEventListener( Event.COMPLETE, handleLoadComplete ); applicationContext.load(); 接着在需要依赖的视图中,我创建一个Inject标签(受一个同事在Parsley中实现的启发)。利用这个标签,我可以很方便的声明我需将何种依赖添加到该视图。例如,在应用启动时,我有如下代码: 这将向XMLApplicationContext请求一个ID为CONTROLLER的对象,并将它赋给视图中的成员变量controller。这是在视图层获取对象的好办法。说明: Christophe Herreman曾撰文 说明如何用metadata实现上述类型的注入(类似Swiz 框架 ,但这种方法有性能问题,因为要读取元数据,视图需序列化为XML。设置控制器Spring ActionScript已计划发布一个支持MVCS的的扩展版。但
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号