在Flex中实现依赖注入
出自9RIA.com WIKI
(英文原文: Dependency injection with Flex ) 原作者:Bill Bejeck 翻译者:Maya
先前写了些关于Flex开发的文章,我感到用Flex开发应用的优点是它和Java开发很像。不只是Java语言,只要你是以写代码为生的,就能很容易地理解我的书,新东西和你接触的语言/平台很像。你将知道:
- ActionScript 3.0的接口构造,以及它和Java接口的等价对比。
- 如何使用ActionScript 3.0中的接口来实现依赖注入。
- 如何在Flex中使用一个简单的依赖注入。
目录 |
准备
本文所需要用到的软件有:
预备知识
阅读本文时,你需要熟悉Flex Builder,尽管不是必须,但会很有用。熟悉面向对象技术,精通ActionScript 3.0。
了解依赖注入
众所周知,面向对象设计能很好得控制类的功能(对于开发人员,你需要灵活得使用这个原则,我这里只是大致阐述下概念)。为了遵循这条原则,对象就要通过使用合作对象来完成自己的使命。但是这些合作对象从哪儿来呢?通常,没有依赖注入,你就需要在你的组件中实例化这些合作对象。对象之间的高耦合度使得你的应用很难维护,也不便于独立地测试组件。依赖注入是一个非常粗略的概念。当你使用容器或框架专门用来把合作对象“注入”给需要他们的各个对象后(详细请参见更正式的定义),它最终就演变成一个强大的模式。你可以独立开发和测试你的对象,然后把他们捆绑在一起来构建你的应用。在Java开发中,Spring框架就是个常见的依赖注入框架。
我将使用Spring框架的一部分,Spring-MVC为例。在Spring-MVC模式中,你有一个Controller对象用来处理来自客户端的访问请求。现今很多web应用,大多是后面有个数据库,应用就通过它提供的数据呈现给用户。假设用户根据作者查询书籍。最简单的方式是,Controller对象接收请求,把作者名字从request参数中挑出,再把条件传给BookService对象,等待返回的书名列表。最后把书名列表反馈给用户。Spring框架在中间所做的处理就是把BookService对象注入到Controller中(通过XML或注释进行配置,超出本文话题)。BookService对象对Java接口的实现意味着service的实现对Controller对象是不可见的。这样很好。只要参数和方法的返回类型不变,Controller对象就不需要了解service是如何工作的。但在Flex开发中需要怎么做?
在ActionScript 3.0接口中实现依赖注入
构造接口给依赖注入提供了活力。用一捆相互依靠才能工作的对象,而不是用某个特定的对象来实现,这就意味着,如果其中一个对象修改了,那么其它所有依赖它的对象都需要进行修改,但这些对象只需要改变相应接口的实现即可。所以实现的修改就变得无缝,测试也很方便。设想一些:既然ActionScript 3.0可以构造同样的接口,那么书写低耦合的代码就很方便。
和在Java里使用接口的方式一样:
1. 定义你的接口。ActionScript 3.0的接口类似:
package com.example {
public interface Controller {
public void search(searchParams:Object, callback:Function=null);
}
}
2.定义一个实现了该接口的类。
package com.example {
public class HttpController implements Controller{
private var _httpService:HTTPService= new HTTPService();
public void search(reqParams:Object, callback:Function=null){
details omitted for clarity
}
}
}
在上面的例子里,有一个名为Controller接口和名为HttpController的实现。当执行search的时候,HttpController用来和你应用的后端交互。它使用Flex对象HTTPService,处理search请求和返回的内容。你可以看到HttpController里实例化了HTTPService。所以为什么不能注入HTTPService对象呢?无缝接口可以随时满足你应用的需求。这种情况下,如果你需要另一个查找机制,就可以写一个简单的实例或修改已有的。
FLEX风格的依赖注入
你已经了解了依赖注入和它对一个好的应用设计的重要性。但如何运用在Flex应用里呢?举个例子,比如你创建了一个组件来接收和处理用户输入信息和查询结果的呈现。这个组件肯定是某种容器。所以要扩展Panel类,实现控制不同的对象来完成你的查询功能。另外,组件的行为完全用ActionScript类定义(在MXML里定义<script></script>标签)。扩展Panel对象的ActionScript文件大致如下例:
public class SearchPanel extends Panel {
private _searchController:Controller;
public function search(text:String):void {
this._searchController.search(text, this.callBackFunction);
}
public function set searchController(searchController:Controller):void {
this._searchController = searchController;
}
public function get searchController():Conroller {
return this._searchController;
}
}
上述例子的一大特点是实例变量,Controller类型的_searchController和其getter和setter方法。名字和_searchController变量去掉“_”的一样。接着,给用来做呈现的MXML组件起名为SearchPanelView.mxml(接着的细节省略...)
<?xml version="1.0" encoding="utf-8"?> <SearchPanel xmlns="bbejeck.example.*" xmlns:comp="bbejeck.example.*"xmlns:mx="http://www.adobe.com/2006/mxml"> <comp:HttpController id="searchController" /> </SearchPanel>
对于上面的MXML,有如下几个要点:
- <comp:HttpController id="searchController" />定义了为SearchPanel所用的controller组件。注意其中定义的类名为HttpController,_searchController实例变量仅为了让它是Controller类型,实现了什么无关紧要。
- id属性要同SearchPanel这个ActionScript类里的getter和setter方法名一致。
- 当Flex应用加载完SearchPanelView.mxml后,“HttpController”就被实例化了,id属性与SearchPanel类里setter方法名匹配的组件Controller实例就被注入到SearchPanel类里面了。
- 当你想要修改你的search功能,你可以修改HttpController对象,或定义一个新的实现类并修改SearchPanelView.mxml文件,无论哪种方法你都完全不需要修改SearchPanel的代码。
总结
你已经知道如何在Flex里使用依赖注入了。Flex应用会把MXML里的id和周围setter里方法名匹配的注入到组件中。我们有必要使用Flex获取基本的依赖注入容器。
我们可以得出结论:
- 当构建应用的时候,不能只考虑构建应用自身,还需要考虑建立应用时需要哪些独立组件,他们的功能是什么。为了构建应用,你准备的组件还需要实现callback和service对象。代码重用很重要,以后你再建立新应用时就快很多了。
- 简化单元测试。现在,如果你的组件拥有基于接口的合作者,那在测试这些组件时,你就可以手工地请求适当的setter方法并把仅实现接口的假对象作为测试用例。
想了解更多
想了解更多关于依赖注入的Flex例子,请从Gumbo上下载Spark,它是下一个版本的Flex框架。
本文的例子来自我先前写的Flex开发中,那里同样所使用的依赖注入也在这里讨论了。
几个开源项目也提供了依赖注入的框架,其中有:
- Swizframework
- Dependency Prana
- Smartypants
还有很多优秀的关于Flex编程的书籍,我想以下几本很有帮助。
- Essential ActionScript 3 by Colin Moock
- Advanced ActionScript 3 with Design Patterns by Joey Lott and Danny Patterson
关于作者
Bill Bejeck是Near Infinity驻北弗吉尼亚的软件工程师。除去和女儿玩耍,他的大部分时间都花在计算机上,你可以通过他的邮箱给他留言。