微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于Java反射机制及控制反转的GUI框架设计

基于Java反射机制及控制反转的GUI框架设计

时间:02-27 来源:3721RD 点击:

3 框架运行机理

框架中各组成部分在运行过程中的调用关系如图1所示。

当程序入口启动时,框架解析bean-config.xml文件;组件工厂类根据xml配置文件创建各种组件对象;组件外观设置类查找xml文件为每个组件设置相应的外观;事件监听器类查找xml文件为每个组件添加对应的事件监听器;事件执行类查找xml文件为每个组件设置事件触发时执行的方法;最后还需要一个保存窗体对象的类。

GUI程序开发人员只需要设置相应的get、set方法来存取组件,事件发生时要执行的方法和配置xml文件。组件的建立、外观的设置、事件监听添加、事件处理方法都由框架来完成。一个编码的例子如下:

public class JFrameDemo extends JFrame{
private JTextField input ;
private JButton ok ;
//省略的get, set方法
//省略构造方法,该方法用于添加组件到窗体
}
//事件处理类和方法
public class EventOperator{
public void operate(){
//从保存窗体对象的类中获得窗体
//通过窗体的get方法获得组件
//执行所需的操作并修改组件状态
}
}

4 框架的具体实现

4.1 xml配置文件格式

xml是一种标记语言,用于各种配置文件和不同语言间交换信息,它只负责信息的存储,而不负责信息的表达。本框架bean-config.xml文件的设计格式如下:

<?xml version="1.0" encoding="GB2312"?>
<beans>
<bean>
<setColumns>10;Integer</setColumns>
</bean>
<bean>
<setText>计算;String</setText>
<event type="ActionListener" method="operate"></event>
</bean>
<bean>
<ref>input</ref>
<ref>ok</ref>
</bean>
</beans>

配置文件说明如下:

(1)根节点为beans。

(2)bean节点中的id属性用来唯一地标识一个组件,该值要与代码里的组件名一致,class属性用来表示所对应的类名。

(3)event节点的type属性表示监听器的类型, class属性表示事件触发时将要执行的方法所对应的类名,method属性表示事件触发时将要执行的方法。如上面xml文件中,表示当ok组件发生单击事件时,将执行test. EventOperator类的operate方法。

(4)ref子节点值表示该组件需要依赖的其他bean的标识。

(5)bean其他子节点为设置组件外观的方法,子节点值为调用该方法所需的参数值和对应的参数类型。

4.2 Java的反射机制

因为所对应的类、方法都保存在xml文件中,而对xml解析得到的类名和方法名都是字符串类型,要把字符串实例化成相应的对象并调用就要用到Java的反射技术[4]。

Java的反射机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的类的内部信息,包括其访问权限、父类、实现接口,也包括成员变量和方法的所有信息,并可在运行时改变成员变量的内容或执行方法。
本框架主要利用反射机制来实例化对象和调用方法。其关键代码如下(className,methodName均为字符串):

Class instance = Class.forName(className).newInstance();
//获得目标类实例,传入目标类名及包名
Class c = Class.forName(className);
Method m = c.getMethod(methodName,new Class[]{...});
//传入方法名和参数类型数组
m.invoke(instance, new Object[]{});
//方法执行,传入目标类的实例和方法参数值数组

4.3 xml文件处理器

xml文件处理器主要用于对bean-config.xml文件进行解析, 本框架采用jdk1.5自带的 org.w3c.dom包来解析xml文档,为文档对象模型(DOM) 提供接口。

xml文件处理器根据传入的xml文件生成Document节点,Document可看做是xml在内存中的一个镜像,对Document操作能够直接同步到该xml文件。关键代码如下:

DocumentBuilderFactory dbf=DocumentBuilderFactory.new
Instance();
DocumentBuilder db=dbf.newDocumentBuilder();
//通过工厂得到一个DocumentBuilder
Document doc=db.parse("bean-config.xml");
//DocumentBuilder通过解析xml文件得到一个Document

4.4 组件工厂类的实现

根据xml文件的bean节点建立组件对象,首先利用Document的getElementsByTagName方法获得所有bean节点的NodeList对象,遍历NodeList对象获得每个bean节点的Node对象,再利用Node的getAttributes方法获得该节点的所有属性,然后根据获得的id、class属性就可以实例化组件。关键代码如下:

NodeList nodes = doc.getElementsByTagName("bean");
//获得所有的bean节点
... ...
Node node = nodes.item(i);//获得其中一个bean节点 NamedNodeMap attributes = node.getAttributes();
//取出该节点的所有属性值
... ...
Class cl = Class.forName(class属性值);   Object instance = cl.newInstance(); //创建该类的实例

4.5 组件外观设置类实现

从组件工厂类中获得组件对象并从xml文件中获得的方法名、参数值和参数类型,利用Java反射技术就可以为组件执行方法设置组件外观。

4.6 事件执行类

事件执行类继承多个事件接口,同时实现接口对应的方法。在每个实现的方法中,获得xml文件中event节点的class属性值以及method属性值,利用Java反射技术就可以执行方法。这时当组件触发事件时,执行事件执行类的对应方法,而事件执行类的方法是调用method属性值的方法。这样就实现了当组件触发事件时,执行method属性值的方法。

通过事件执行类,可以自定义触发事件时执行的方法名,实现了事件监听与事件处理的分离。事件执行类采用单例模式实现即仅有一个实例运行,节省了内存消耗。

4.7 事件监听器添加类

传统GUI编程中,事件监听器的添加是利用组件调用相应的方法,并传入对应的事件监听器对象。在本框架事件监听器添加类中,首先获得event节点的type属性值,通过Java反射技术把事件执行类实例添加到组件中,这样当组件触发事件时就可以执行事件执行类的相关方法。

在GUI设计中将组件设计和事件处理交予本文框架管理,降低了对象之间的依赖程度。在代码中仅需要编写get、set方法,也不需注册监听器、实现接口等代码,减少了代码编写量,实现了业务对象的松散耦合。事件触发和事件执行实现了分离,提高了程序的可维护性。对组件状态或事件信息的改变不需修改源代码,只需要修改配置文件,易于实现重构。

实践表明,该框架简单易用,建立的图形用户界面(GUI)具有较高的灵活性、可维护性和可扩展性,对构建中小型的GUI应用具有良好的支撑作用和借鉴意义。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top