<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>


    posts - 15,  comments - 34,  trackbacks - 27
    在對(duì)一個(gè)J2EE項(xiàng)目的重構(gòu)、增加新功能的過(guò)程中,對(duì)客戶端GUI程序,我們使用了State模式。結(jié)果顯示,該模式的使用,不但減少了客戶端GUI程序的程序規(guī)模(LOC),而且,該部分的開發(fā)及單元測(cè)試時(shí)間大大減少,同時(shí),在集成測(cè)試中發(fā)現(xiàn)的缺陷數(shù)量比使用該模式前平均減少了3倍。本文就該項(xiàng)目中使用State模式的方式進(jìn)行介紹。

    引言
    在分層軟件體系結(jié)構(gòu)中,服務(wù)端程序關(guān)注于實(shí)現(xiàn)業(yè)務(wù)邏輯,客戶端程序則包含用戶界面。服務(wù)端程序由客戶端程序調(diào)用,其請(qǐng)求、響應(yīng)模式在設(shè)計(jì)時(shí)已經(jīng)確定,運(yùn)行時(shí)出現(xiàn)問(wèn)題的概率較小。相反,客戶端程序與用戶直接交互,雖然有正確規(guī)定的操作順序或模式,但是用戶的操作是不可預(yù)知的,程序必須處理各種操作錯(cuò)誤、加上數(shù)據(jù)輸入有效驗(yàn)證等要求,使得客戶端程序的開發(fā)成本上升。

    因而,一旦有經(jīng)過(guò)充分測(cè)試的、甚至是通過(guò)驗(yàn)收的用戶交互程序GUI,應(yīng)該盡可能的重用該GUI,以提高軟件的可靠性、可維護(hù)性。

    在對(duì)一個(gè)J2EE項(xiàng)目的重構(gòu)、增加新功能的過(guò)程中,對(duì)客戶端GUI程序,我們使用了State模式。結(jié)果顯示,該模式的使用,不但減少了客戶端GUI程序的程序規(guī)模(LOC),而且,該部分的開發(fā)及單元測(cè)試時(shí)間大大減少,同時(shí),在集成測(cè)試中發(fā)現(xiàn)的缺陷數(shù)量比使用該模式前平均減少了3倍。本文就該項(xiàng)目中使用State模式的方式進(jìn)行介紹。

    1. State模式
    首先,先簡(jiǎn)單介紹一下State模式。

    該模式是指在對(duì)象的內(nèi)部狀態(tài)改變時(shí)改變對(duì)象的行為【1】。其結(jié)構(gòu)如圖1所示。

    圖1 State模式結(jié)構(gòu)
    圖1 State模式結(jié)構(gòu)

    模式中各個(gè)參與者職責(zé)簡(jiǎn)介如下:

    • Context:用戶對(duì)象,擁有一個(gè)State類型的成員,以標(biāo)識(shí)對(duì)象的當(dāng)前狀態(tài);
    • State:接口或基類,封裝與Context的特定狀態(tài)相關(guān)的行為;
    • ConcreteState:接口實(shí)現(xiàn)類或子類,實(shí)現(xiàn)了一個(gè)與Context某個(gè)狀態(tài)相關(guān)的行為。

    運(yùn)行時(shí),Context將與狀態(tài)相關(guān)的請(qǐng)求委托給當(dāng)前的ConcreteState對(duì)象處理。關(guān)于State模式更詳盡的介紹,請(qǐng)參閱參考文獻(xiàn)1。

    2. 客戶端應(yīng)用
    本模式的目標(biāo)是分離客戶端軟件中的變化部分與不變部分,以使得變化的部分可獨(dú)立于不變的部分,有利于擴(kuò)充新的功能,也有利于維護(hù)。

    在項(xiàng)目中,對(duì)于客戶端GUI的重用有兩種方式。

    • 方式1適用于:相同數(shù)據(jù)集合,不同操作模式;此時(shí),在GUI中定義客戶端數(shù)據(jù)處理驗(yàn)證邏輯,不同的狀態(tài)對(duì)象封裝了不同的操作模式;
    • 方式2適用于:不同數(shù)據(jù)集合,相同操作模式;此時(shí),在狀態(tài)對(duì)象中定義客戶端數(shù)據(jù)處理驗(yàn)證邏輯,不同的狀態(tài)對(duì)象封裝了不同的數(shù)據(jù)集合操作。

    2.1 類型1: Read-Only & Normal
    2.1.1 動(dòng)機(jī)

    客戶端GUI接受用戶輸入,經(jīng)過(guò)數(shù)據(jù)有效性驗(yàn)證,然后將數(shù)據(jù)傳輸?shù)椒?wù)端,服務(wù)端檢查業(yè)務(wù)邏輯有效性,保存數(shù)據(jù);但是在特定情況下(比如數(shù)據(jù)已經(jīng)存在、且只能經(jīng)歷一次輸入),依據(jù)客戶端GUI所操作數(shù)據(jù)的狀態(tài),業(yè)務(wù)邏輯要求數(shù)據(jù)為只讀,即客戶端只具有顯示數(shù)據(jù)的功能,并不能改變服務(wù)器上的數(shù)據(jù)。

    一般地,編程實(shí)現(xiàn)時(shí),會(huì)在GUI程序中加入判斷數(shù)據(jù)是否應(yīng)該為只讀的邏輯判斷語(yǔ)句。如果針對(duì)相同的數(shù)據(jù)集合(Model),有多個(gè)客戶端GUI(View),就需要在每個(gè)程序中加入該判斷。如此降低了程序的可維護(hù)性,決定數(shù)據(jù)是否為只讀的這樣一個(gè)業(yè)務(wù)邏輯將分散在程序中多處,不易維護(hù),在業(yè)務(wù)邏輯發(fā)生改變時(shí),易造成不一致。

    我們可以將變化部分(在Normal和Read-Only狀態(tài)下不同的部分)從GUI中抽取出來(lái),分別用不同的類來(lái)表示,這樣,當(dāng)GUI的狀態(tài)發(fā)生改變時(shí),只需要改變其對(duì)狀態(tài)對(duì)象的引用即可,狀態(tài)相關(guān)操作委托給狀態(tài)對(duì)象去完成。

    2.1.2 適用性

    本類型適用環(huán)境:相同數(shù)據(jù)集合,不同操作模式。即特定的GUI根據(jù)操作上下文環(huán)境,改變其響應(yīng)模式,根據(jù)數(shù)據(jù)是否可編輯,分為兩種狀態(tài)Read-Only State、 Normal State。

    2.1.3 結(jié)構(gòu)(圖2)

    圖2 相同數(shù)據(jù)集合,不同操作模式
    圖2  相同數(shù)據(jù)集合,不同操作模式

    2.1.4 參與者

    • ClientStateChangeable:客戶端GUI提供給State對(duì)象的操作接口,使得State對(duì)象可以訪問(wèn)GUI的成員,以完成該狀態(tài)相關(guān)操作;
      • getChangeableComponents():返回在狀態(tài)轉(zhuǎn)換為Read-Only時(shí),不可編輯的控件Collection;
      • saveChangeToServer():在可編輯狀態(tài)時(shí),將客戶端數(shù)據(jù)保存到服務(wù)端。
    • AClientGUI:完成圖1中的Context功能,即其狀態(tài)要進(jìn)行改變的客戶端GUI;維護(hù)ClientState的一個(gè)實(shí)例(state);
      • init():將this引用作為參數(shù),調(diào)用state.setComponents(this) 以設(shè)置可變控件的初始狀態(tài);
      • okButtonActionPerformed(e:ActionEvent):用戶完成操作后,本方法可作為 "OK"按鈕控件的ActionListener方法,調(diào)用state.action(this) 以完成本操作。
    • ClientState:State接口,封裝與客戶端GUI某個(gè)特定狀態(tài)相關(guān)的行為;
      • setComponents(gui:ClientStateChangeable):設(shè)置參數(shù)gui指定的客戶端GUI的控件狀態(tài);
      • action(gui:ClientStateChangeable):完成數(shù)據(jù)保存功能。
    • ClientNormalState:可編輯狀態(tài)子類,實(shí)現(xiàn)ClientState接口;
      • setComponents(gui:ClientStateChangeable):調(diào)用參數(shù)gui指定的客戶端GUI的getChangeableComponents()獲取控件Collection,然后遍歷設(shè)置各控件狀態(tài)為可編輯;
      • action(gui:ClientStateChangeable):調(diào)用參數(shù)gui指定的客戶端GUI的saveChangeToServer()完成數(shù)據(jù)保存功能。
    • ClientReadOnlyState:只讀狀態(tài)子類,實(shí)現(xiàn)ClientState接口;
      • setComponents(gui:ClientStateChangeable):調(diào)用參數(shù)gui指定的客戶端GUI的getChangeableComponents()獲取控件Collection,然后遍歷設(shè)置各控件狀態(tài)為ReadOnly;
      • action(gui:ClientStateChangeable):空方法,本狀態(tài)下無(wú)數(shù)據(jù)變化,無(wú)須保存。

    2.1.5 代碼示例

    ClientStateChangeable接口:


    
    public interface ClientStateChangeable {	
    	/**
    	 * To get all changeable components in the GUI object. 
    	 * @return Collection contains Component objects. 
    	 */
    	Collection getChageableComponents();
    	
    	/**
    	 * To save data to server.
    	 */
    	void saveChangeToServer();
    }
    

    AClientGUI類:


    
    public class AClientGUI extends JPanel implements ClientStateChangeable{
    	//… 	
    	private ClientState state = null;
    
    public DesignStep1View(ClientState state){
    //…			
    this.state = state;
    this.state.setComponents(this);
    	}
    	
    	private void okButton_actionPerformed(ActionEvent e){
    		state.action(this);	//save data
    	}
    
    	public Collection getChageableComponents() {
    		Collection dataComponents = new ArrayList();		
    		dataComponents.add(jComboBoxESEPattern);
    		//…			
    		return dataComponents;
    	}
    
    	public void saveChangeToServer() {
    		//…	
    	}
    }
    

    ClientState接口:

    public interface ClientState { /** * To set components' state in the GUI. * @param gui a GUI object which implements StateChangeable interface. */ void setComponents(ClientStateChangeable gui); /** * when user click OK-Button in a GUI, the GUI will call this method. * @param gui a GUI object which implements StateChangeable interface. */ void action(ClientStateChangeable gui); }

    ClientNormalState類:


    olor="#CCCCCC">
    
    public class ClientNormalState implements ClientState {
    	/**
    	 * 正常狀態(tài)下, 各個(gè)控件默認(rèn)為可編輯的, 所以不用做任何更改
    	 */
    	public void setComponents(ClientStateChangeable gui) {}
    
    	/** 
    	 * 正常狀態(tài)下, 需要將用戶所作修改保存到服務(wù)端 
    	 */
    	public void action(ClientStateChangeable gui) {
    		gui.saveChangeToServer();
    	}
    }
    

    ClientReadOnlyState類:


    
    public class ClientReadOnlyState implements ClientState {
    	/**
    	 * 設(shè)置GUI的數(shù)據(jù)控件為Read-Only
    	 */
    public void setComponents(ClientStateChangeable gui) {
    		Collection components = gui.getChageableComponents();
    		Iterator iter = components.iterator();
    		while(iter.hasNext()){
    			JComponent jc = (JComponent)iter.next();
    			jc.setEnabled(false);			
    			String toolTip = jc.getToolTipText();
    			String addedTip = "只讀狀態(tài)";
    			if(toolTip == null)toolTip = addedTip;
    			else toolTip += ". " + addedTip;
    			jc.setToolTipText(toolTip); 
    		}
    	}
    
    	/**
    	 * GUI處于Read-Only狀態(tài), 無(wú)需將數(shù)據(jù)保存到server端	
    	 */
    	public void action(ClientStateChangeable gui) {}
    }
    

    2.2 類型2:(Reuse GUI)
    2.2.1 動(dòng)機(jī)

    當(dāng)多個(gè)客戶端GUI布局、控件類型很相似,所完成的任務(wù)也相似時(shí),只需要經(jīng)過(guò)精心設(shè)計(jì),將這些GUI的展示形式統(tǒng)一起來(lái),同一個(gè)GUI可以用到多個(gè)場(chǎng)景中,達(dá)到重用的目的。此時(shí),這些不同任務(wù)需要操作不同的數(shù)據(jù)集合。

    可以在GUI類中實(shí)現(xiàn)這些不同數(shù)據(jù)集合的操作,但是這會(huì)給程序維護(hù)帶來(lái)麻煩。首先,屬于不同邏輯的數(shù)據(jù)操作出現(xiàn)在同一類文件中,造成邏輯混亂、程序規(guī)模增大,不易于調(diào)試;其次,要將GUI用于新的數(shù)據(jù)集合時(shí),只能在相同文件中增加新的代碼,此時(shí),該程序的可維護(hù)性降低,尤其是新的工作由其他程序員完成時(shí),要理解原有代碼是很費(fèi)力的。

    和2.1.1節(jié)中提到的解決方法類似:將變化的部分和不變部分分離開來(lái),使得變化的部分可以獨(dú)立修改、擴(kuò)充。具體地,則是將數(shù)據(jù)集合相關(guān)操作從GUI程序中抽取出來(lái),定義一個(gè)所有數(shù)據(jù)集合操作的接口(即:狀態(tài)接口),不同地?cái)?shù)據(jù)集合操作作為該接口的一個(gè)實(shí)現(xiàn)類存在。這樣,每個(gè)數(shù)據(jù)集合都獨(dú)立的封裝于一個(gè)狀態(tài)對(duì)象內(nèi);而且,要對(duì)新的數(shù)據(jù)使用該GUI,只需要定義新的狀態(tài)接口實(shí)現(xiàn)類即可,無(wú)須修改已有類,甚至不關(guān)心已有的狀態(tài)。

    2.2.2 適用性

    本類型適用環(huán)境:不同的數(shù)據(jù)集合,相同的操作模式。即不變化的客戶端GUI,將不同的數(shù)據(jù)集合操作委托給變化的狀態(tài)對(duì)象去完成。

    2.2.3 結(jié)構(gòu)(圖3)

    圖3 不同數(shù)據(jù)集合,相同操作模式
    圖3 不同數(shù)據(jù)集合,相同操作模式

    2.2.4 參與者

    • InvariableGUI:本身不發(fā)生變化的客戶端GUI類,維護(hù)一個(gè)對(duì)VariableDataState的引用state,將數(shù)據(jù)相關(guān)操作委托給該引用對(duì)象 ;
      • saveChangeToServer():調(diào)用state.processData(this)完成數(shù)據(jù)相關(guān)操作;
    • VariableDataState:State接口,封裝與數(shù)據(jù)相關(guān)操作的行為;
      • ProcessData(gui:InvariableGUI):調(diào)用參數(shù)gui的成員獲取數(shù)據(jù)并完成處理;
    • DataState1、DataState2、 … … DataStateN:狀態(tài)子類,實(shí)現(xiàn)VariableDataState接口,封裝了特定某一類數(shù)據(jù)集合的操作,可以根據(jù)不同的數(shù)據(jù)集合定義多個(gè)VariableDataState接口的狀態(tài)類,從而實(shí)現(xiàn)了對(duì)InvariableGUI的重用。

    本類型的實(shí)現(xiàn)代碼在這里就不列出了,參照2.1.5節(jié)中的代碼,很容易的就可實(shí)現(xiàn)本類型的結(jié)構(gòu)。

    2.3 綜合以上兩種類型
    可以將以上兩種類型結(jié)合起來(lái)使用,即實(shí)現(xiàn)了客戶端軟件的數(shù)據(jù)集合方面對(duì)GUI的重用,也實(shí)現(xiàn)了操作模式方面對(duì)GUI的重用。

    程序?qū)崿F(xiàn)時(shí),可以由GUI類分別維護(hù)一個(gè)ClientState的引用和一個(gè)VariableDataState的引用:

    • 初始化GUI類時(shí),GUI的構(gòu)造器調(diào)用ClientState對(duì)象的setComponents()方法設(shè)置控件的狀態(tài);
    • 用戶提交操作時(shí),GUI調(diào)用ClientState對(duì)象的action()方法,如圖2所示,該方法使用傳遞的gui參數(shù)回調(diào)GUI的saveChangeToServer()方法,而saveChangeToServer()方法則按照?qǐng)D3所示,調(diào)用VariableDataState引用的狀態(tài)對(duì)象的processData()方法完成數(shù)據(jù)操作。

    3 總結(jié)
    本文介紹的State模式應(yīng)用于多類型數(shù)據(jù)、多操作模式的客戶端軟件,可以取得明顯的效果;但如果客戶端類和狀態(tài)都很少時(shí),使用本模式,反而增加了客戶端類數(shù)量,增加了體系結(jié)構(gòu)的復(fù)雜性,此時(shí),可以使用繼承方式的類體系來(lái)實(shí)現(xiàn)重用,無(wú)須使用State狀態(tài)對(duì)象的委托操作和回調(diào)操作。

    posted on 2005-02-05 20:09 jacky 閱讀(393) 評(píng)論(0)  編輯  收藏 所屬分類: Design Patten

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(10)

    隨筆檔案

    文章分類

    文章檔案

    相冊(cè)

    收藏夾

    java

    搜索

    •  

    最新評(píng)論


    主站蜘蛛池模板: 亚洲人成伊人成综合网久久久 | 四虎成人精品国产永久免费无码| 无码专区一va亚洲v专区在线 | 日本人护士免费xxxx视频| 久久国产精品免费| 亚洲av永久无码精品天堂久久| 免费国产怡红院在线观看| 无码一区二区三区免费| 亚洲成AV人片在WWW| 久久国产精品亚洲综合| 免费理论片51人人看电影| 日本免费污片中国特一级| 综合一区自拍亚洲综合图区 | 中文字幕亚洲男人的天堂网络 | 蜜桃视频在线观看免费网址入口 | 日韩a在线观看免费观看| 免费无码一区二区三区| 亚洲1区2区3区精华液| 久久久久久亚洲Av无码精品专口| 国产自产拍精品视频免费看| 99在线免费观看视频| 欧洲乱码伦视频免费国产| 亚洲av无码片在线观看| 国产亚洲综合一区柠檬导航| 国产精品视频免费一区二区三区| 最刺激黄a大片免费网站| 国产精品成人免费观看| 亚洲精品无码专区久久| 亚洲福利一区二区精品秒拍| 亚洲一区AV无码少妇电影☆| 国产免费av片在线播放| 黄色成人网站免费无码av| 精品无码国产污污污免费网站| caoporm超免费公开视频| 亚洲av无码专区青青草原| 亚洲乱码一二三四区国产| 亚洲精品综合一二三区在线| 久久久久亚洲av毛片大| 亚洲 国产 图片| 日韩免费视频网站| 最新仑乱免费视频|