您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 其它文档 > 基于Java泛型对Spring中强制类型转换工厂的改进
中强制类型转换工厂的改进苗锡奎辽宁工程技术大学电子与信息工程学院,辽宁葫芦岛(125105)E-mail:miaoxikui@163.com摘要:本文主要利用泛型编程将泛型机制与设计模式有机的结合并加以优化和实现,提出一种提出利用了Java的新特性—泛型类型(generictype),在工厂设计模式或其它应用中摆脱类类型在强制转换或向下类型转换的过程中极容易发生的错误的设计方案。并针对Spring中的强制类型转换的工厂进行了改进,在利用工厂获得某个类的实例时不需要硬编码的方式强制转换实例的类型。关键词:泛型,泛型编程,工厂模式,XML中图分类号:TP3111.引言软件的解耦一直是软件研究领域的一个热点课题。所产生的思想也数不胜数,其中的两大重要思想是Ioc思想和Aop思想,然而这些思想都是种种设计模式的体现。其中的工厂设计模式就在这两种思想中都有所体现。然而工厂模式虽然优势很多但是也存在着不足之处。在面向对象设计的软件中我们与软件打交道的无疑都是一个个的对象,而且一个软件的灵活性是与软件的整个软件的体系结构设计的好坏有直接的关系。而如何井井有条地产生与组织对象就变的首当其冲了。工厂模式中的简单工厂模式是有效产生和管理对象的有利工具。在软件的体系结构设计过程中为了达到软件功能的解耦常常利用设计模式对软件进行建设。工厂方法就是解耦的一种有效的途径。在Spring中就应用了大量的工厂方法,它可以通过配置文件的配置信息来得到某个类的实例[1]。而不用通过硬编码的方式如Aa=newA()来产生对象,使对象与产生对象的类之间在程序中观察不出任何的联系来。无论是采用面向接口方式编程来使软件的解耦程度更上一层楼还是直接面向类编程,利用工厂方法都必须在对象显示产生的时候为其强制指定某种类型,这不仅为程序的编写者带来了不必要的麻烦,而且在一定的程度上改善了软件体系结构的可扩展性。Java是一种强类型的语言,Java的安全和健壮性部分来自于它是该类型语言这一事实。Java编译器对所有的表达式和参数都要进行类型相容性的检查以保证类型是兼容的。任何类型的不匹配都是错误的,在编译器完成编译以前,错误必须被改正。例如我们有抽象类A和其实现类AA或接口B和其实现类BB,利用Spring的工厂产生类BB的实例的时候就必须写成如下格式:Aa=(BB)BeanFactory.getBean(“bb”);当然这仅仅是类型转换的一种。这就要求程序员必须严格的遵守这一规则,当然遵守这一规则带来的安全性和健壮性要远远大于不遵守这一规则所带来的方便性。但是我们可以在特定的环境下,利用泛型机制将这一规则所带来的约束降低到最小。基于以上存在的问题,提出了可以在程序运行过程中动态的产生对象并不用强制为其指定类型的一种可行的设计方案。2.方案介绍2.1简单工厂模式简介在工厂模式的简单工厂模式中,工厂处于对产品类进行实例化的中心位置上,它知道每一个产品类的细节,并决定在何时哪一个产品类应当被实例化。实质上就是由一个工厂类根据传入的参量决定创建出哪一种产品的实例。可以用一个示意性的图来表示简单工厂模式的结构。图2.1简单工厂模式的结构图简单工厂模式的优点是能够使客户端独立于产品的创建过程,并且在系统中引入新产品时无需对客户端进行修改,缺点是当有新产品要加入到系统中时,必须对工厂类进行修改,以加入必要的处理逻辑。简单工厂模式的致命弱点就是处于核心地位的工厂类,因为一旦它无法确定要对哪个类进行实例化时,就无法使用该模式[2]。2.2方案简介针对2.1中所述的简单工厂模式的原理即是根据传入的参量决定创建出哪一种产品的实例和其致命弱点,我们可以从传入的“参量”为突破口结合Java泛型机制,利用Apache的CommonsDigester组件来有效合理的组织配置文件,从而实现工厂根据系统的配置文件的不同参量来产生不同类的实例。其过程可以详述为:系统读取按照一定格式设计的配置文件中的参量,然后把此参量所携带的信息进行进一步的加工和提取,最后把它转换成与配置文件的配置项相对应的对象,工厂利用该对象所携带的信息利用泛型产生与该信息相对应的实例。CommonsDigester组件的工作原理不是本文所介绍的重点,故未详细叙述,可以参考有关文档。这样不但可以有效的改进简单工厂模式的缺点使该模式在当有新产品要加入到系统中时不必修改处于核心地位的工厂类,而且可以为程序的编写者摆脱类类型在强制转换或向下类型转换的过程中极容易发生的错误所带来的不便和使软件的解耦性。该方案可以形象地解释成“工厂根据配置文件的信息产生对象,该对象就可以直接的赋值给抽象的引用、接口的引用或类的引用,而不用对其进行强制类型的转换”。3.方案的设计3.1配置文件格式的定义由于该方案是模拟从配置文件中读取将要生产的“产品”的信息,因此十分有必要对“产品”所表示的信息格式化,工厂可以可以根据不同的参量或者配置信息得到不同的“产品”,进而实现了“产品对象”的可配置性。如果要增加新的“产品”,就可以在配置文件中填加,无须对工厂类进行修改。在这个方案中,是通过采用XML配置文件的方式来实现“产品”信息的封装。工厂在生产“产品”的时候通过Digester组件将XML配置项(产品信息)转换成相应的对象的,以便可以得到各种关于该“产品”的所有有用的信息,工厂就是利用这个信息来生产“产品”的。为使本方案的设计与实现达到“不相对复杂化”,并且与Spring配置文件进行对比之后决定采用如下格式的配置文件:=1.0encoding=UTF-8?configuratoinproductsproductid=”product”type=”xi.kui.miao.XxxProduct”single=”false”args0=”XxxProduct”args1=”F-x-1”/………/products/configuration考虑到本文所将要实现的重点并不是在此,而是仅仅用product节点元素模拟某个产品应该有的一些信息,而不至于使方案的设计和实现复杂化。当然读者完全可以根据自己的业务需求和业务模型相应地为“产品”的填加必要信息,这完全不是技术难题了。故在此也为给出configuration、products两个节点元素的基本信息,并且也没有给出该XML配置文件的DTD文件。配置文件的格式一目了然,根元素configuration表示这是一个全局的配置信息。在configuration元素内包含了一个products元素,这就是“产品”配置信息的集合。Products元素所包含的每一个product元素就代表了一个基本的“产品”信息。下面给出product节点元素详细的说明:id:产品的唯一标识。type:与产品相对应的产品类。single:表示在由工厂生产该产品时,是否是全局唯一。single=”true”:表示工厂生产的某种产品只有一个产品实例,single=”false”:表示工厂生产的某种产品的产品实例个不相同。single默认为true。argsi:i=0,1,2….表示该产品的构造方法的参数。本方案只考虑了字符串类型的参数,若要扩展可以自行填加。根据Digester组件的工作原理,需要定义与节点元素相应的类。Configuration类和Product类分别与configuration和product节点元素对应,其实现见后文。3.2方案的类图类图是用于对系统的静态设计视图建模[3],所以该方案是用类图来说明其静态的结构。根据上述方案所存在的类、属要及方案实现的功能,可以给出该方案的静态结构。由于方案的设计是通用的所以对面向接口变成还是面向类编程或是面向抽象编程了产品对该方案的实现都无影响,因此对产品的类并没有做设计。方案的时序图时序图描述了以时间顺序组织的对象之间的交互活动[3],因此本方案采用时序图来描述其行为。可以根据类之间的交互可以很容易地分析类中应该有那些责任(方法),进而在实现方案的时候完善类中的方法。图3.3方案的时序图方案的优化设计程序质量的好坏直接影响了程序的执行速度,因此对方案的优化十分必要。3.4.1读取配置文件的工具类的优化在工厂生产产品的时候主要是根据配置文件的信息来产生的,因此在设计读取配置文件的类的时应该考虑通过一个静态的Configuration类的实例来保存解析后的根配置对象。之所以这样做是因为在这个工具类中生成的根配置对象应该是全局唯一的且面向大众共享的。同时解析配置文件的规则和对象的生成代码都应该放到静态代码块中,从而保证该代码块只在该工具类加载的时候执行一次,其它时候都不会执行。次这样就不需要在每次读取配置文件的时候重新进行解析操作。3.4.2工厂类和产品类的优化该工厂可以达到在程序中动态的根据参量的不同来获取类的信息(如构造方法,方法和方法的参数等)来产生不同的对象。而该对象的类型就完全可以不加强制类型转换直接赋给是声明的引用。首先在工厂中能够直接获得产品的配置项对象的信息,而把生产“产品”的具体任务仍然交给产品本身,这体现了类的封装性,提高了模块的内聚性。在产品类中引入了一个工具类CreateProductUtil来辅助产品类,以使产品类更加简单。之所以在这里就生成对象的实例,主要是出于对运行效率的考虑。在这里可以根据single的值和构造方法的参数来生成符合要求的实例。4.方案的实现在对方案的静态视图和动态视图分析了之后,就可以对方案的类图做进一步的细化,即可以对类进行编码了。4.1方案的构件图构件图展现了构件之间的组织与依赖,而组件是开发和运行时的物理对象的类,它专注于系统的静态实现[4]。因此用构件图可以很清楚的展现案的静该方态实现。图4.1方案的构件图4.2配置项类的实现根据配置文件的格式和节点元素,本方案只实现了configuration和product两个节点元素的配置类,分别为Configuration和Product。在这里没有实现products节点元素的配置类,主要原因是products元素的作用只是将product元素封装起来,本身没有任何属性。但Configuration是整个XML文件的根元素,在生成Java对象后,将是所有子元素的的容器。另外如果configuration还可能在将来加入其它子元素,可以在方案扩展的时候使配置文件结构上更加清晰一些。类中的成员和方法可以参见类图,可以很容易根据Java的语法写出类文件[5]。4.3其它类的实现CreateFactory、ConfigurationUtil、CreateProductUtil分别是工厂类、读取配置文件的工具类、产品的辅助类。根据上文的类图可以确定类所拥有的基本的成员,而根据时序图可以很容易地确定出类中需要增加的交互功能的成员,最终形成类文件。5.结论该方案对简单工厂模式采用了读取配置文件方式来获得“产品”的信息之后,利用泛型机制来在程序运行过程中动态地根据不同的参量产生对象,使得在由工厂获得“产品”的时候相对传统的简单工厂模式有了很大的改进,使得获得的“产品”没有必要进行类型的转型就可以赋给声明的变量。同时由于配置文件的存在,增加“产品”的种类时不用修改工厂类,体现了软件设计的“开—闭原则”即对扩展开放,对修改关闭。但在Spring的工厂中,当生产“产品”时必须进行类型的转换才能赋给声明的变量,这在程序员十分熟悉程序的情况下增加了编程的复杂性。不加强制类型转换直接赋给是声明的引用。当然是有一定的好处的,同时也会有一定的弊端的,这主要取决于该方案的应用环境了,如果在特定的应用条件下注重编程的简单性和
本文标题:基于Java泛型对Spring中强制类型转换工厂的改进
链接地址:https://www.777doc.com/doc-506298 .html