`

三十四:MLProperties与适配器模式

阅读更多
一:问题
几乎所有的应用程序都有一些系统常量需要存储在程序外部,一个常见的做法是使用一个配置文件存储这些常量,这样,一旦常量有变化的话,无需修改程序代码就可以重新配置一个系统。在Java编程里,一个配置文件就是.properties文件或者XML文件。使用.properties文件虽然是现行工业标准,但正在渐渐被XML文件所取代,一个配置文件所需要的无非就是存储一些代码和代码所代表的值组成的对,即key-value对,如.properties配置文件的内容代码清单:
name=milenfan 
website=www.milenfan.com 
email=jyumath_Milenfan@163.com 
如果将此配置文件改写成XML文件的话,代码如下: 
<property name="name"> 
milenfan 
</property> 
<property name="website"> 
www.milenfan.com 
</property> 
<property name="email"> 
jyumath_milenfan@163.com 
</property> 


使用XML文件是一个好主意,唯一不足的是读取XML文件不像读取.properties文件那样容易,因为Java语言为.properties文件准备了java.util.Properties类,那么可不可以自己提供一个读取XML配置文件的工具类呢?当然可以。如果是单纯读取XML文件的话,事情并不复杂,但是有一些已经开发完成的系统已经使用了.properties文件,将.properties文件更换为.xml文件的话就要修改读取配置文件的代码,这就不符合软件设计的"开-闭"原则.那么能否在将.properties文件更换为.xml文件的同时不修改代码呢?当然可以。如果使用适配器模式的话是可以做到这一点的.假设这个类叫做XMLProperties,那么XMLProperties需要能读取XML文件,但是提供给客户端的是一个Properties类型。换言之,XMLProperties将XML接口适配成java.util.Properties类型.
如果你不熟悉SAX2(Simple API for XML),我为你额外提供了XML和SAX2教程的快照.(关于SAX2的事件处理请参巧观察者模式与SAX2浏览器一章)

二:SAX2浏览器
(A)SAX2是什么
SAX是Simple API for XML的缩写,它是一个通用的为各种不同的XML浏览器而设计的接口,就像jdbc是为各种不同的数据库而设计的接口一样。使用SAX接口而不是直接使用XML浏览器本身,可以避免使应用程序依赖于这种XML浏览器.与DOM比较而言,SAX是一种轻量型的方法,在处理DOM时需要读入整个XML文件,然后在内存中创建DOM的树结构,包括生成DOM树上的每个节点对象。当文件比较小时,这不会造成什么问题,但是一旦文件大起来,处理DOM就会耗费相当大的资源。这时候,一个很好的办法就是使用SAX。
不同于DOM的文档驱动,SAX是事件驱动的,也就是说,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程,所谓事件驱动,就是java1.1所提出的委派事件模型机制.
XMLReader读入文档的过程和解析的过程是同时进行的,解析开始之前,需要向XMLReader注册一个ContentHandler,也就是相当于一个事件监听器,在ContentHandler中定义了很多事件方法,作为对遇到一个XML标识符事件的相应方法,比如startDocument(),它定义了在解析过程中遇到文档开始时采取的操作,当XMLReader读到合适的内容时,就会抛出相应的事件,并把这个事件的处理权委派给ContentHandler,而后者则调用相应的方法作为响应.
你可以去下载org.apache.xeroes.parsers.SAXParser这个驱动包
下面是一个读取XML文件的例子:
package cai.milenfan.basic.test; 
import java.io.FileReader; 
import org.xml.sax.InputSource; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax.helpers.XMLReaderFactory; 

public class MySAXApp extends DefaultHandler{ 
public MySAXApp(){ 
super(); 
} 
public static void main(String[] args)throws Exception{ 
XMLReader xr = XMLReaderFactory.createXMLReader(); 
MySAXApp handler = new MySAXApp(); 
//把MySAXApp的一个实例登记到XMLReader里,以接收正常的内宾事件和出错事件,还可以登记其他事件 
xr.setContentHandler(handler); 
xr.setErrorHandler(handler); 
FileReader fr = new FileReader(args[0]); 
xr.parse(new InputSource(fr)); 
} 
//开始读xml时触发的方法 
public void startDocument(){ 
System.out.println(".................startDocument");
} 
//读取xml完毕时触发的方法 
public void endDocument(){ 
System.out.println(".................endDocument");
} 
//SAX2遇到普通的character数据时会通过character方法报告给客户端 
public void character(char ch[],int start,int length){ 
System.out.println(".................character");
for(int i=start;i&lt;start + length;i++){ 
System.out.println(ch[i]); 
} 
} 
} 

三:下面开始解决"一"中提到的问题
本项目的目的是使用适配器模式将DocumentHandler的接口适配成java.util.Properties的接口.在这里采取对象的适配器模式,XMLProperties是一个继承自java.util.Properties的对象,并委派一个DocumentHandler类型的对象.这就是说,本项目需要两个新类--XMLProperties类和XMLParser类,前者的类型是java.util.Properties,后者的类型是DocumentHandler。
390---用SAX解释xml的源码。很不错! (在此略过,遇到问题,如何初始化XMLParser)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics