您的位置:首页 > 编程语言 > Java开发

Java私塾:研磨设计模式 之 解释器模式(Interpreter)1

2013-12-06 09:43 756 查看

21.1 场景问题

21.1.1 读取配置文件

考虑这样一个实际的应用,维护系统自定义的配置文件。几乎每个实际的应用系统都有与应用自身相关的配置文件,这个配置文件是由开发人员根据需要自定义的,系统运行时会根据配置的数据进行相应的功能处理。 系统现有的配置数据很简单,主要是JDBC所需要的数据,还有默认读取Spring的配置文件,目前系统只需要一个Spring的配置文件。示例如下:
<?xml version="1.0" encoding="UTF-8"?><root> <jdbc> <driver-class>驱动类名</driver-class> <url>连接数据库的URL</url> <user>连接数据库的用户名</user> <password>连接数据库的密码</password> </jdbc> <application-xml>缺省读取的Spring配置的文件名称</application-xml></root>
现在的功能需求是:如何能够灵活的读取配置文件的内容?

21.1.2 不用模式的解决方案

不就是读取配置文件吗?实现很简单,直接读取并解析xml就可以了。读取xml的应用包很多,这里都不用,直接采用最基础的Dom解析就可以了。另外,读取到xml中的值过后,后续如何处理,这里也不去管,这里只是实现把配置文件读取并解析出来。 按照这个思路,很快就写出了实现的代码,示例代码如下:
/** * 读取配置文件 */public class ReadAppXml { /** * 读取配置文件内容 * @param filePathName 配置文件的路径和文件名 * @throws Exception */ public void read(String filePathName)throws Exception{ Document doc = null; //建立一个解析器工厂 DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance(); //获得一个DocumentBuilder对象,这个对象代表了具体的DOM解析器 DocumentBuilder builder=factory.newDocumentBuilder(); //得到一个表示XML文档的Document对象 doc=builder.parse(filePathName); //去掉XML中作为格式化内容的空白而映射在DOM树中的Text Node对象 doc.normalize();
//获取jdbc的配置值 NodeList jdbc = doc.getElementsByTagName("jdbc"); //只有一个jdbc,获取jdbc中的驱动类的名称 NodeList driverClassNode = ((Element)jdbc.item(0)).getElementsByTagName("driver-class"); String driverClass = driverClassNode.item(0).getFirstChild().getNodeValue(); System.out.println("driverClass=="+driverClass); //同理获取url、user、password等的值 NodeList urlNode = ((Element)jdbc.item(0)).getElementsByTagName("url"); String url=urlNode.item(0).getFirstChild().getNodeValue(); System.out.println("url=="+url);
NodeList userNode = ((Element)jdbc.item(0)).getElementsByTagName("user"); String user = userNode.item(0).getFirstChild().getNodeValue(); System.out.println("user=="+user);
NodeList passwordNode = ((Element)jdbc.item(0)).getElementsByTagName("password"); String password = passwordNode.item(0).getFirstChild().getNodeValue(); System.out.println("password=="+password);
//获取application-xml NodeList applicationXmlNode =doc.getElementsByTagName("application-xml"); String applicationXml = applicationXmlNode.item(0).getFirstChild().getNodeValue(); System.out.println("applicationXml=="+applicationXml); }}

21.1.3 有何问题

看了上面的实现,多简单啊,就是最基本的Dom解析嘛,要是采用其它的开源工具包,比如dom4j、jDom之类的来处理,会更简单,这好像不值得一提呀,真的是这样吗?请思考一个问题:如果配置文件的结构需要变动呢?仔细想想,就会感觉出问题来了。还是先看例子,然后再来总结这个问题。随着开发的深入进行,越来越多可配置的数据被抽取出来,需要添加到配置文件中,比如与数据库的连接配置:就加入了是否需要、是否使用DataSource等配置。除了这些还加入了一些其它需要配置的数据,例如:系统管理员、日志记录方式、缓存线程的间隔时长、默认读取哪些Spring配置文件等等,示例如下:
<?xml version="1.0" encoding="UTF-8"?><root> <database-connection> <connection-type>连接数据库的类型,1-用Spring集成的方式(也就是不用下面两种方式了),2-DataSource(就是使用JNDI),3-使用JDBC自己来连接数据库 </connection-type> <jndi>DataSource的方式用,服务器数据源的JNDI名称</jndi> <jdbc>跟上面一样,省略了</jdbc> </database-connection> <system-operator>系统管理员ID</system-operator> <log> <operate-type>记录日志的方式,1-数据库,2-文件</operate-type> <file-name>记录日志的文件名称</file-name> </log> <thread-interval>缓存线程的间隔时长</thread-interval> <spring-default> <application-xmls> <application-xml>缺省读取的Spring配置的文件名称 </application-xml> <application-xml>其它需要读取的Spring配置的文件名称 </application-xml> </application-xmls> </spring-default></root>
有朋友可能会想,改变一下配置文件,值得大惊小怪吗?对于应用系统开发来讲,这不是经常发生的、很普通的一件事情嘛。 的确是这样,改变一下配置文件不是件大事情,但是带来的一系列麻烦也不容忽视,比如:修改了配置文件的结构,那么读取配置文件的程序就需要做出相应的变更;用来封装配置文件数据的数据对象也需要相应的修改;外部使用配置文件的地方,获取数据的地方也会相应变动。 当然在这一系列麻烦中,最让人痛苦的莫过于修改读取配置文件的程序了,有时候几乎是重写。比如在使用Dom读取第一个配置文件,读取默认的Spring配置文件的值的时候,可能的片断代码示例如下:
//获取application-xml NodeList applicationXmlNode =doc.getElementsByTagName("application-xml"); String applicationXml = applicationXmlNode.item(0).getFirstChild().getNodeValue(); System.out.println("applicationXml=="+applicationXml);
但是如果配置文件改成第二个,文件的结构发生了改变,需要读取的配置文件变成了多个了,读取的程序也发生了改变,而且application-xml节点也不是直接从doc下获取了。几乎是完全重写了,此时可能的片断代码示例如下:
//先要获取spring-default,然后获取application-xmls //然后才能获取application-xml NodeList springDefaultNode =doc.getElementsByTagName("spring-default"); NodeList appXmlsNode = ((Element)springDefaultNode.item(0)).getElementsByTagName("application-xmls"); NodeList appXmlNode = ((Element)appXmlsNode.item(0)).getElementsByTagName("application-xml"); //循环获取每个application-xml元素的值 for(int i=0;i<appXmlNode.getLength();i++){ String applicationXml = appXmlNode.item(i).getFirstChild().getNodeValue(); System.out.println("applicationXml=="+applicationXml); }
仔细对比上面在xml变化前后读取值的代码,你会发现,由于xml结构的变化,导致读取xml文件内容的代码,基本上完全重写了。问题还不仅仅限于读取元素的值,同样体现在读取属性上。可能有些朋友说可以换不同的xml解析方式来简化,不是还有Sax解析,实在不行换用其它开源的解决方案。 确实通过使用不同的解析xml的方式是会让程序变得简单点,但是每次xml的结构发生变化过后,或多或少都是需要修改程序中解析xml部分的。 有没有办法解决这个问题呢?也就是当xml的结构发生改变过后,能够很方便的获取相应元素、或者是属性的值,而不用再去修改解析xml的程序。更多内容搜索“Java私塾”即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息