<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 基于Java反射機制及控制反轉的GUI框架設計

基于Java反射機制及控制反轉的GUI框架設計

作者: 時(shí)間:2012-03-27 來(lái)源:網(wǎng)絡(luò ) 收藏

是目前最優(yōu)秀的軟件開(kāi)發(fā)語(yǔ)言之一,由于其結構簡(jiǎn)單、面向對象、跨平臺等優(yōu)越特性使它具有極強的生存力,并得到了廣泛的應用?;?a class="contentlabel" href="http://dyxdggzs.com/news/listbylabel/label/Java">Java(GUI)中,AWT是提供的用來(lái)建立和設置Java的第一代開(kāi)發(fā)工具。AWT由java.awt包提供,其中包含了許多可以用來(lái)建立與平臺無(wú)關(guān)的GUI類(lèi)。由于A(yíng)WT組件占有系統資源較多,常把java.awt組件稱(chēng)為重量級組件。Java Swing是Java Foundation Classes(JFC)的一部分,解決了AWT的很多缺點(diǎn),相對于A(yíng)WT,Swing是輕量級組件。Swing提供了許多比AWT更好的屏幕顯示元素,使用純Java寫(xiě)成,與Java一樣可以跨平臺運行[1]。

(GUI)借助于多種組件,包括菜單、按鈕、文本框、選擇框、列表框等,通過(guò)相應的事件處理機制,實(shí)現與用戶(hù)的動(dòng)態(tài)交互。

1 圖形用戶(hù)界面的建立

1.1 創(chuàng )建GUI窗口

javax.swing.JFrame類(lèi)是用來(lái)建立用戶(hù)界面的底層窗口容器,能夠容納其他組件的對象,如標簽、按鈕、文本組件等。JFrame類(lèi)提供的add()方法把不同的組件添加到容器中,通過(guò)容器類(lèi)的setLayout()方法可以設定容器的布局,安排各種組件在容器中。

使用JFrame類(lèi)創(chuàng )建GUI窗口的基本步驟如下:用JFrame類(lèi)或其子類(lèi)創(chuàng )建一個(gè)對象即窗體;設置窗口的部分屬性,如標題、寬度、高度、可見(jiàn)性、圖標等;添加內容面板、組件;編寫(xiě)事件處理方法;組件添加事件監聽(tīng)。

1.2 Java事件處理

在Java中,程序與用戶(hù)的交互通過(guò)響應各種事件來(lái)實(shí)現。每當一個(gè)事件發(fā)生,Java虛擬機就會(huì )將事件的消息傳遞給程序,由程序中的事件處理方法對事件進(jìn)行處理。Java通過(guò)委托型事件處理機制來(lái)解決對事件的響應。
事件處理機制可表述如下[2]:事件源對象封裝了事件源、組件狀態(tài)等必要信息;當事件源對象發(fā)生改變時(shí),向它所注冊的所有監聽(tīng)器發(fā)出通知,各監聽(tīng)器判斷事件類(lèi)型是否為自己管轄范圍,若是,則通知給該監聽(tīng)器的執行器,執行器從事件中獲取事件信息,并執行相應函數,改變組件的狀態(tài)。

1.3 傳統創(chuàng )建窗口和事件處理的局限性

在傳統的GUI創(chuàng )建過(guò)程中,存在一些局限性。

(1)組件創(chuàng )建、添加都采用硬編碼方式,造成程序的過(guò)度耦合。

(2)如果窗體中有很多組件,組件要添加注冊監聽(tīng),則在代碼中看到很多重復注冊監聽(tīng)的代碼,而這些注冊監聽(tīng)的代碼都與界面本身設計無(wú)關(guān),組件與事件之間的映射關(guān)系將會(huì )很混亂。

(3)事件處理方法定義在別的類(lèi)中,無(wú)法得到窗體及其組件的引用,只能得到事件源,而無(wú)法改變其他組件的狀態(tài);或者把事件處理與窗體設計放在一起,這樣程序的可維護性又不好。

(4)不利于代碼重用,基于MVC的思想,應該把事件處理方法分離出來(lái);在需要修改事件處理代碼時(shí),就無(wú)需修改界面本身的源代碼。

2 圖形用戶(hù)界面設計的改進(jìn)

2.1 控制反轉(IOC)

IOC就是控制反轉[3](Inversion of Control)的縮寫(xiě),也稱(chēng)為依賴(lài)注入,控制反轉IOC是一種用于控制業(yè)務(wù)對象之間依賴(lài)關(guān)系的機制,將其設計的類(lèi)與類(lèi)之間的關(guān)系都交由外部容器進(jìn)行管理,僅需調用類(lèi)在容器中注冊的名字就可以得到類(lèi)的實(shí)例,有效降低了業(yè)務(wù)對象之間的依賴(lài)程度,實(shí)現了業(yè)務(wù)對象之間的松散耦合。
IOC的實(shí)際意義就是把組件之間的依賴(lài)關(guān)系(調用關(guān)系)反轉出來(lái),對象之前的依賴(lài)關(guān)系用xml配置文件描述;這樣,各個(gè)組件之間就不存在硬編碼的關(guān)聯(lián),任何組件都可以最大程度地得到重用。
考慮如下接口和類(lèi)的定義:
public interface ICar{void operate();}
public class Toyota implements ICar{…}
public class Honda implements ICar{…}
public class Driver{
private ICar car;
public void setCar(ICar car){this.car = car;}
public ICar getCar(){return car;}
public void drive(){car.operator();}
}

類(lèi)Driver依賴(lài)于ICar,而類(lèi)Toyota和Honda實(shí)現了接口ICar,即類(lèi)Driver可以依賴(lài)于Toyota或Honda。
運用了IOC模式后就不再需要自己管理組件之間的依賴(lài)關(guān)系,只需要聲明由xml配置文件描述去實(shí)現這種依賴(lài)關(guān)系,就好像把對組件之間的依賴(lài)關(guān)系的控制進(jìn)行了倒置,不再由組件自己來(lái)建立這種依賴(lài)關(guān)系而是交給xml配置文件去管理。

2.2 設計的改進(jìn)

在改進(jìn)的GUI編程中,把窗體中組件的創(chuàng )建、組件的外觀(guān)設置和組件觸發(fā)事件時(shí)執行什么方法,不是以硬編碼的方式組合在一起,而是通過(guò)配置文件來(lái)配置。這樣開(kāi)發(fā)人員無(wú)須關(guān)心組件的創(chuàng )建、組件的樣式設置、事件的監聽(tīng)與實(shí)現,只需要設置相應的get、set方法來(lái)存取組件、屬性等,事件處理方法能在任意類(lèi)中實(shí)現,方法名可以自定義,并且在其他類(lèi)中能夠得到窗體對象及其組件的引用。當組件的樣式發(fā)生改變時(shí),只需改動(dòng)配置文件即可。

該改進(jìn)設計通過(guò)配置文件,并利用控制反轉和Java反射機制得以實(shí)現,這就需要有框架和良好的設計。

3 框架運行機理

框架中各組成部分在運行過(guò)程中的調用關(guān)系如圖1所示。

當程序入口啟動(dòng)時(shí),框架解析bean-config.xml文件;組件工廠(chǎng)類(lèi)根據xml配置文件創(chuàng )建各種組件對象;組件外觀(guān)設置類(lèi)查找xml文件為每個(gè)組件設置相應的外觀(guān);類(lèi)查找xml文件為每個(gè)組件添加對應的;事件執行類(lèi)查找xml文件為每個(gè)組件設置事件觸發(fā)時(shí)執行的方法;最后還需要一個(gè)保存窗體對象的類(lèi)。

本文引用地址:http://dyxdggzs.com/article/257615.htm

GUI程序開(kāi)發(fā)人員只需要設置相應的get、set方法來(lái)存取組件,事件發(fā)生時(shí)要執行的方法和配置xml文件。組件的建立、外觀(guān)的設置、事件監聽(tīng)添加、事件處理方法都由框架來(lái)完成。一個(gè)編碼的例子如下:

public class JFrameDemo extends JFrame{
private JTextField input ;
private JButton ok ;
//省略的get, set方法
//省略構造方法,該方法用于添加組件到窗體
}
//事件處理類(lèi)和方法
public class EventOperator{
public void operate(){
//從保存窗體對象的類(lèi)中獲得窗體
//通過(guò)窗體的get方法獲得組件
//執行所需的操作并修改組件狀態(tài)
}
}

4 框架的具體實(shí)現

4.1 xml配置文件格式

xml是一種標記語(yǔ)言,用于各種配置文件和不同語(yǔ)言間交換信息,它只負責信息的存儲,而不負責信息的表達。本框架bean-config.xml文件的設計格式如下:

?xml version=1.0 encoding=GB2312?>
beans>
bean id=input class=java.awt.JTextField>
setColumns>10;Integer/setColumns>
/bean>
bean id=ok class=java.awt.JButton>
setText>計算;String/setText>
event type=ActionListener class=test.Event-
Operator method=operate>/event>
/bean>
bean id=frame class=test.JFrameDemo>
ref>input/ref>
ref>ok/ref>
/bean>
/beans>

配置文件說(shuō)明如下:

(1)根節點(diǎn)為beans。

(2)bean節點(diǎn)中的id屬性用來(lái)唯一地標識一個(gè)組件,該值要與代碼里的組件名一致,class屬性用來(lái)表示所對應的類(lèi)名。

(3)event節點(diǎn)的type屬性表示監聽(tīng)器的類(lèi)型, class屬性表示事件觸發(fā)時(shí)將要執行的方法所對應的類(lèi)名,method屬性表示事件觸發(fā)時(shí)將要執行的方法。如上面xml文件中,表示當ok組件發(fā)生單擊事件時(shí),將執行test. EventOperator類(lèi)的operate方法。

(4)ref子節點(diǎn)值表示該組件需要依賴(lài)的其他bean的標識。

(5)bean其他子節點(diǎn)為設置組件外觀(guān)的方法,子節點(diǎn)值為調用該方法所需的參數值和對應的參數類(lèi)型。

4.2 Java的反射機制

因為所對應的類(lèi)、方法都保存在xml文件中,而對xml解析得到的類(lèi)名和方法名都是字符串類(lèi)型,要把字符串實(shí)例化成相應的對象并調用就要用到Java的反射技術(shù)[4]。

Java的反射機制允許程序在運行時(shí)透過(guò)Reflection APIs取得任何一個(gè)已知名稱(chēng)的類(lèi)的內部信息,包括其訪(fǎng)問(wèn)權限、父類(lèi)、實(shí)現接口,也包括成員變量和方法的所有信息,并可在運行時(shí)改變成員變量的內容或執行方法。
本框架主要利用反射機制來(lái)實(shí)例化對象和調用方法。其關(guān)鍵代碼如下(className,methodName均為字符串):

Class instance = Class.forName(className).newInstance();
//獲得目標類(lèi)實(shí)例,傳入目標類(lèi)名及包名
Class c = Class.forName(className);
Method m = c.getMethod(methodName,new Class[]{...});
//傳入方法名和參數類(lèi)型數組
m.invoke(instance, new Object[]{});
//方法執行,傳入目標類(lèi)的實(shí)例和方法參數值數組

4.3 xml文件處理器

xml文件處理器主要用于對bean-config.xml文件進(jìn)行解析, 本框架采用jdk1.5自帶的 org.w3c.dom包來(lái)解析xml文檔,為文檔對象模型(DOM) 提供接口。

xml文件處理器根據傳入的xml文件生成Document節點(diǎn),Document可看做是xml在內存中的一個(gè)鏡像,對Document操作能夠直接同步到該xml文件。關(guān)鍵代碼如下:

DocumentBuilderFactory dbf=DocumentBuilderFactory.new
Instance();
DocumentBuilder db=dbf.newDocumentBuilder();
//通過(guò)工廠(chǎng)得到一個(gè)DocumentBuilder
Document doc=db.parse(bean-config.xml);
//DocumentBuilder通過(guò)解析xml文件得到一個(gè)Document

4.4 組件工廠(chǎng)類(lèi)的實(shí)現

根據xml文件的bean節點(diǎn)建立組件對象,首先利用Document的getElementsByTagName方法獲得所有bean節點(diǎn)的NodeList對象,遍歷NodeList對象獲得每個(gè)bean節點(diǎn)的Node對象,再利用Node的getAttributes方法獲得該節點(diǎn)的所有屬性,然后根據獲得的id、class屬性就可以實(shí)例化組件。關(guān)鍵代碼如下:

NodeList nodes = doc.getElementsByTagName(bean);
//獲得所有的bean節點(diǎn)
... ...
Node node = nodes.item(i);//獲得其中一個(gè)bean節點(diǎn) NamedNodeMap attributes = node.getAttributes();
//取出該節點(diǎn)的所有屬性值
... ...
Class cl = Class.forName(class屬性值);   Object instance = cl.newInstance(); //創(chuàng )建該類(lèi)的實(shí)例

4.5 組件外觀(guān)設置類(lèi)實(shí)現

從組件工廠(chǎng)類(lèi)中獲得組件對象并從xml文件中獲得的方法名、參數值和參數類(lèi)型,利用Java反射技術(shù)就可以為組件執行方法設置組件外觀(guān)。

4.6 事件執行類(lèi)

事件執行類(lèi)繼承多個(gè)事件接口,同時(shí)實(shí)現接口對應的方法。在每個(gè)實(shí)現的方法中,獲得xml文件中event節點(diǎn)的class屬性值以及method屬性值,利用Java反射技術(shù)就可以執行方法。這時(shí)當組件觸發(fā)事件時(shí),執行事件執行類(lèi)的對應方法,而事件執行類(lèi)的方法是調用method屬性值的方法。這樣就實(shí)現了當組件觸發(fā)事件時(shí),執行method屬性值的方法。

通過(guò)事件執行類(lèi),可以自定義觸發(fā)事件時(shí)執行的方法名,實(shí)現了事件監聽(tīng)與事件處理的分離。事件執行類(lèi)采用單例模式實(shí)現即僅有一個(gè)實(shí)例運行,節省了內存消耗。

4.7 添加類(lèi)

傳統GUI編程中,事件監聽(tīng)器的添加是利用組件調用相應的方法,并傳入對應的事件監聽(tīng)器對象。在本框架事件監聽(tīng)器添加類(lèi)中,首先獲得event節點(diǎn)的type屬性值,通過(guò)Java反射技術(shù)把事件執行類(lèi)實(shí)例添加到組件中,這樣當組件觸發(fā)事件時(shí)就可以執行事件執行類(lèi)的相關(guān)方法。

在GUI設計中將組件設計和事件處理交予本文框架管理,降低了對象之間的依賴(lài)程度。在代碼中僅需要編寫(xiě)get、set方法,也不需注冊監聽(tīng)器、實(shí)現接口等代碼,減少了代碼編寫(xiě)量,實(shí)現了業(yè)務(wù)對象的松散耦合。事件觸發(fā)和事件執行實(shí)現了分離,提高了程序的可維護性。對組件狀態(tài)或事件信息的改變不需修改源代碼,只需要修改配置文件,易于實(shí)現重構。

實(shí)踐表明,該框架簡(jiǎn)單易用,建立的圖形用戶(hù)界面(GUI)具有較高的靈活性、可維護性和可擴展性,對構建中小型的GUI應用具有良好的支撐作用和借鑒意義。



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>