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

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

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

    iNeo

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      30 Posts :: 8 Stories :: 2 Comments :: 0 Trackbacks

    #

    我的tomcat工程建在:d:\eclipse\workspace\luc,索引文件是d:\eclipse\workspace\luc\public\index,建立索引的時候路徑為"luc\\public\\index",但在搜索的時候,我用
    searcher = new IndexSearcher(“luc\\public\\index”);
    報錯了,因為lucene在FSDirectory里將我的路徑給new File(file.getCanonicalPath());
    但奇怪的是file.getCanonicalPath()出來路徑不對呀
    錯誤是
    java.io.IOException: D:\eclipse\luc\public\index not a directory
    應該是d:\eclipse\workspace\luc\public\index 才對的
    郁悶很久了,現在還沒辦法解決!!!!!!!!!!!!!!!!!!!!!!!!!!
    posted @ 2006-08-03 09:12 只牽這只狗 閱讀(328) | 評論 (0)編輯 收藏

    今天上午升級 Eclipse 3.1.2 版本,完了之后就想找個數據庫的插件,但花了近 2 個小時后得出的結論是:還沒有支持 3.1.x 版本的數據庫插件,郁悶的不行??纯?/span> eclipse3.1.12 的發行日期—— 2005.12.26 ,咳,去年 12 月份出的,想不到到現在還沒有支持的版本。當然也可能是我沒找到。如果哪位兄臺能給個支持 3.1.x 版本的數據庫插件,將不甚感激!

    雖然沒找到正主,但還是找到了一些 Eclipse3.0.x 版本可用的版本,以共將來參考。

    SQLExplorer
    SQLExplorer 可以通過JDBC訪問幾乎任何一種數據庫。同時也支持像Hibernate這樣的工具訪問數據庫?,F在的版本是SQLExporer 2.2.4 released。

    下栽地址:http://sourceforge.net/projects/eclipsesql

    JFaceDBC

    是一個很好的 SQL 控制臺 , 支持各類主流數據庫。現在的版本是 JFaceDbc 3.0

    下栽地址:http://sourceforge.net/projects/jfacedbc

    Quantum
    Quantum 是一個數據庫訪問插件.它當前支持的數據庫有:Postgres,MySQL,Adabas,DB2,Oracle與有JDBC驅動的數據庫.它可以顯示表格,視圖并提供一個語法可高亮顯示的SQL編輯器

    com.quantum.feature_3.0.1.bin.dist

    下栽地址:http://sourceforge.net/project/showfiles.php?group_id=7746&package_id=57047

    posted @ 2006-03-30 12:42 只牽這只狗 閱讀(3640) | 評論 (1)編輯 收藏

    TMD..........

    posted @ 2006-03-15 16:54 只牽這只狗 閱讀(221) | 評論 (0)編輯 收藏

    任何人都可以重構

    使用 Eclipse 自動重構特性的方法與原因

     

     

    未顯示需要 JavaScript 的文檔選項


    對此頁的評價

     


    級別: 初級

    David Gallardo, 獨立軟件顧問和作家

    2003 年 11 月 10 日

    Eclipse 提供了一組強大的自動重構(refactoring)功能,這些功能穿插在其他功能當中,使您能夠重命名 Java元素,移動類和包,從具體的類中創建接口,將嵌套的類變成頂級類,以及從舊方法的代碼片斷中析取出新的方法。您熟悉了 Eclipse 的重構工具之后,就掌握了一種提高生產率的好方法。本文綜覽Eclipse 的重構特性,并通過例子闡明了使用這些特性的方法與原因。

    為什么重構?

    重構是指在不改變程序功能的前提下改變其結構。重構是一項功能強大的技術,但是執行起來需要倍加小心才行。主要的危險在于可能在不經意中引入一些錯誤,尤其是在進行手工重構的時候更是如此。這種危險引發了對重構技術的普遍批評:當代碼不會崩潰的時候為什么要修改它呢?

    您需要進行代碼重構的原因可能有以下幾個:傳說中的第一個原因是:需要繼承為某個古老產品而開發的年代久遠的代碼,或者突然碰到這些代碼。最初的開發團隊已經不在了。我們必須創建增加了新特性的新版本軟件,但是這些代碼已經無法理解了。新的開發隊伍夜以繼日地工作,破譯代碼然后映射代碼,經過大量的規劃與設計之后,人們將這些代碼分割成碎片。歷經重重磨難之后,所有這些東西都按照新版本的要求歸位了。這是英雄般的重構故事,幾乎沒有人能在經歷了這些之后活著講述這樣的故事。

    還有一種現實一些的情況是項目中加入了新的需求,需要對設計進行修改。至于是因為在最初的規劃過程中失察,還是由于采用了迭代式的開發過程(比如敏捷開發,或者是測試驅動的開發)而在開發過程中有意引入需求,這兩者并沒有實質性的區別。這樣的重構的規模要小得多,其內容一般涉及通過引入接口或者抽象類來更改類的繼承關系,以及對類進行分割和重新組織,等等。

    重構的最后一個原因是,當存在可用的自動重構工具時,可以有一個用來預先生成代碼的快捷方式——就好比在您無法確定如何拼寫某個單詞的時候,可以用某種拼寫檢查工具輸入這個單詞。比如說,您可以用這種平淡無奇的重構方法生成 getter 和 setter 方法,一旦熟悉了這樣的工具,它就可以為您節省很多的時間。

    Eclipse 的重構工具無意進行英雄級的重構——適合這種規模的工具幾乎沒有——但是不論是否用到敏捷開發技術,Eclipse 的工具對于一般程序員修改代碼的工作都具有無法衡量的價值。畢竟任何復雜的操作只要能夠自動進行,就可以不那么煩悶了。只要您知道 Eclipse 實現了什么樣的重構工具,并理解了它們的適用情況,您的生產力就會得到極大的提高。

    要降低對代碼造成破壞的風險,有兩種重要的方法。第一種方法是對代碼進行一套完全徹底的單元測試:在重構之前和之后都必須通過這樣的測試。第二種方法是使用自動化的工具來進行重構,比如說 Eclipse 的重構特性。

    將徹底的測試與自動化重構結合起來就會更加有效了,這樣重構也就從一種神秘的藝術變成了有用的日常工具。為了增加新的功能或者改進代碼的可維護性,我們可以在不影響原有代碼功能的基礎上迅速且安全地改變其結構。這種能力會對您設計和開發代碼的方式產生極大的影響,即便是您沒有將其結合到正式的敏捷方法中也沒有關系。



    回頁首


    Eclipse 中重構的類型

    Eclipse 的重構工具可以分為三大類(下面的順序也就是這些工具在 Refactoring 菜單中出現的順序):

    1. 對代碼進行重命名以及改變代碼的物理結構,包括對屬性、變量、類以及接口重新命名,還有移動包和類等。
    2. 改變類一級的代碼邏輯結構,包括將匿名類轉變為嵌套類,將嵌套類轉變為頂級類、根據具體的類創建接口,以及從一個類中將方法或者屬性移到子類或者父類中。
    3. 改變一個類內部的代碼,包括將局部變量變成類的屬性、將某個方法中選中部分的代碼變成一個獨立的方法、以及為屬性生成 getter 和 setter 方法。

    還有幾個重構工具并不能完全歸入這三個種類,特別是 Change Method Signature,不過在本文中還是將這個工具歸入第三類。除了這種例外情況以外,本文下面幾節都是按照上面的順序來討論 Eclipse 重構工具的。



    回頁首


    物理重組與重命名

    顯然,您即便沒有特別的工具,也可以在文件系統中重命名文件或者是移動文件,但是如果操作對象是 Java 源代碼文件,您就需要編輯很多文件,更新其中的 import package 語句。與此類似,用某種文本編輯器的搜索與替換功能也可以很容易地給類、方法和變量重新命名,但是這樣做的時候必須十分小心,因為不同的類可能具有名稱相似的方法或者變量;要是從頭到尾檢查項目中所有的文件,來保證每個東西的標識和修改的正確性,那可真夠乏味的。

    Eclipse 的 Rename 和 Move 工具能夠十分聰明地在整個項目中完成這樣的修改,而不需要用戶的干涉。這是因為 Eclipse 可以理解代碼的語義,從而能夠識別出對某個特定方法、變量或者類名稱的引用。簡化這一任務有助于確保方法、變量和類的名稱能夠清晰地指示其用途。

    我們經常可以發現代碼的名字不恰當或者令人容易誤解,這是因為代碼與最初設計的功能有所不同。比方說,某個用來在文件中查找特定單詞的程序也許會擴展為在 Web 頁面中通過 URL 獲取 InputStream 的操作。如果這一輸入流最初叫做 file ,那么就應該修改它的名字,以便能反映其新增的更加一般的特性,比方說 sourceStream 。開發人員經常無法成功地修改這些名稱,因為這個過程是十分混亂和乏味的。這當然也會把下一個不得不對這些類進行操作的開發人員弄糊涂。

    要對某個 Java 元素進行重命名,只需要簡單地從 Package Explorer 視圖中點擊這個元素,或者從Java 源代碼文件中選中這個元素,然后選擇菜單項 Refactor > Rename。在對話框中輸入新的名稱,然后選擇是否需要 Eclipse 也改變對這個名稱的引用。實際顯示出來的確切內容與您所選元素的類型有關。比方說,如果選擇的屬性具有 getter 和 setter 方法,那么也就可以同時更新這些方法的名稱,以反映新的屬性。圖1顯示了一個簡單的例子。

    圖 1. 重命名一個局部變量
    Renaming a local variable

    就像所有的 Eclipse 重構操作一樣,當您指定了全部用來執行重構的必要信息之后,您就可以點擊 Preview 按鈕,然后在一個對話框中對比 Eclipse 打算進行哪些變更,您可以分別否決或者確認每一個受到影響的文件中的每一項變更。如果您對于 Eclipse 正確執行變更的能力有信心的話,您可以只按下 OK按鈕。顯然,如果您不確定重構到底做了什么事情,您就會想先預覽一下,但是對于 Rename 和 Move 這樣簡單的重構而言,通常沒有必要預覽。

    Move 操作與 Rename 十分相似:您選擇某個 Java 元素(通常是一個類),為其指定一個新位置,并定義是否需要更新引用。然后,您可以選擇 Preview檢查變更情況,或者選擇 OK 立即執行重構,如圖2所示。

    圖 2. 將類從一個包移到另一個包
    Moving a class

    在某些平臺上(特別是 Windows),您還可以在 Package Explorer 視圖中通過簡單拖放的方法將類從一個包或者文件夾中移到另一個包或文件夾中。所有的引用都會自動更新。



    回頁首


    重新定義類的關系

    Eclipse 中有大量的重構工具,使您能夠自動改變類的關系。這些重構工具并沒有 Eclipse 提供的其他工具那么常用,但是很有價值,因為它們能夠執行非常復雜的任務??梢哉f,當它們用得上的時候,就會非常有用。

    提升匿名類與嵌套類

    Convert Anonymous Class(轉換匿名類)和 Convert Nested Type(轉換嵌套類)這兩種重構方法比較相似,它們都將某個類從其當前范圍移動到包含這個類的范圍上。

    匿名類是一種語法速寫標記,使您能夠在需要實現某個抽象類或者接口的地方創建一個類的實例,而不需要顯式提供類的名稱。比如在創建用戶界面中的監聽器時,就經常用到匿名類。在清單1中,假設 Bag 是在其他地方定義的一個接口,其中聲明了兩個方法, get() set() 。


    清單 1. Bag 類
     
          public class BagExample
    {
       void processMessage(String msg)
       {
          Bag bag = new Bag()
          {
             Object o;
             public Object get()
             {
                return o;
             }
             public void set(Object o)
             {
                this.o = o;
             }
          };
          bag.set(msg);
          MessagePipe pipe = new MessagePipe();
          pipe.send(bag);
       }
    }
    

    當匿名類變得很大,其中的代碼難以閱讀的時候,您就應該考慮將這個匿名類變成嚴格意義上的類;為了保持封裝性(換句話說,就是將它隱藏起來,使得不必知道它的外部類不知道它),您應該將其變成嵌套類,而不是頂級類。您可以在這個匿名類的內部點擊,然后選擇 Refactor > Convert Anonymous Class to Nested 就可以了。當出現確認對話框的時候,為這個類輸入名稱,比如 BagImpl ,然后選擇 Preview或者 OK。這樣,代碼就變成了如清單2所示的情形。


    清單 2. 經過重構的 Bag 類
     
    
    public class BagExample
    {
       private final class BagImpl implements Bag
       {
          Object o;
          public Object get()
          {
             return o;
          }
          public void set(Object o)
          {
             this.o = o;
          }
       }
           
       void processMessage(String msg)
       {
         Bag bag = new BagImpl();
         bag.set(msg);
         MessagePipe pipe = new MessagePipe();
         pipe.send(bag);
       }
    }

    當您想讓其他的類使用某個嵌套類時,Convert Nested Type to Top Level 就很有用了。比方說,您可以在一個類中使用值對象,就像上面的 BagImpl 類那樣。如果您后來又決定應該在多個類之間共享這個數據,那么重構操作就能從這個嵌套類中創建新的類文件。您可以在源代碼文件中高亮選中類名稱(或者在 Outline 視圖中點擊類的名稱),然后選擇 Refactor > Convert Nested Type to Top Level,這樣就實現了重構。

    這種重構要求您為裝入實例提供一個名字。重構工具也會提供建議的名稱,比如 example ,您可以接受這個名字。這個名字的意思過一會兒就清楚了。點擊 OK 之后,外層類 BagExample 就會變成清單3所示的樣子。


    清單 3. 經過重構的 Bag 類
    
    public class BagExample
    {
       void processMessage(String msg)
       {
          Bag bag = new BagImpl(this);
          bag.set(msg);
          MessagePipe pipe = new MessagePipe();
          pipe.send(bag);
       }
    }
    

    請注意,當一個類是嵌套類的時候,它可以訪問其外層類的成員。為了保留這種功能,重構過程將一個裝入類 BagExample 的實例放在前面那個嵌套類中。這就是之前要求您輸入名稱的實例變量。同時也創建了用于設置這個實例變量的構造函數。重構過程創建的新類 BagImpl 如清單4所示。


    清單 4. BagImpl 類
      
    final class BagImpl implements Bag
    {
       private final BagExample example;
       /**
        * @paramBagExample
        */
      BagImpl(BagExample example)
       {
          this.example = example;
          // TODO Auto-generated constructor stub
       }
       Object o;
       public Object get()
       {
          return o;
       }
       public void set(Object o)
       {
          this.o = o;
       }
    }
    

    如果您的情況與這個例子相同,不需要保留對 BagExample 的訪問,您也可以很安全地刪除這個實例變量與構造函數,將 BagExample 類中的代碼改成缺省的無參數構造函數。

    在類繼承關系內移動成員

    還有兩個重構工具,Push Down 和 Pull Up,分別實現將類方法或者屬性從一個類移動到其子類或父類中。假設您有一個名為 Vehicle 的抽象類,其定義如清單5所示。


    清單 5. 抽象的 Vehicle 類
    
    public abstract class Vehicle
    {
       protected int passengers;
       protected String motor;
       
       public int getPassengers()
       {
          return passengers;
       }
       public void setPassengers(int i)
       {
          passengers = i;
       }
       public String getMotor()
       {
          return motor;
       }
       public void setMotor(String string)
       {
          motor = string;
       }
    }
    

    您還有一個 Vehicle 的子類,類名為 Automobile ,如清單6所示。


    清單6. Automobile 類
    
    public class Automobile extends Vehicle
    {
       private String make;
       private String model;
       public String getMake()
       {
          return make;
       }
       public String getModel()
       {
          return model;
       }
       public void setMake(String string)
       {
          make = string;
       }
       public void setModel(String string)
       {
          model = string;
       }
    }
    

    請注意, Vehicle 有一個屬性是 motor 。如果您知道您將永遠只處理汽車,那么這樣做就好了;但是如果您也允許出現劃艇之類的東西,那么您就需要將 motor 屬性從 Vehicle 類下放到 Automobile 類中。為此,您可以在 Outline 視圖中選擇 motor ,然后選擇 Refactor > Push Down

    Eclipse 還是挺聰明的,它知道您不可能總是單單移動某個屬性本身,因此還提供了 Add Required 按鈕,不過在 Eclipse 2.1 中,這個功能并不總是能正確地工作。您需要驗證一下,看所有依賴于這個屬性的方法是否都推到了下一層。在本例中,這樣的方法有兩個,即與 motor 相伴的 getter 和 setter 方法,如圖3所示。

    圖 3. 加入所需的成員
    Adding required members

    在按過 OK按鈕之后, motor 屬性以及 getMotor() setMotor() 方法就會移動到 Automobile 類中。清單7顯示了在進行了這次重構之后 Automobile 類的情形。


    清單 7. 經過重構的 Automobile 類
    public class Automobile extends Vehicle
    {
       private String make;
       private String model;
       protected String motor;
       public String getMake()
       {
          return make;
       }
       public String getModel()
       {
          return model;
       }
       public void setMake(String string)
       {
          make = string;
       }
       public void setModel(String string)
       {
          model = string;
       }
       public String getMotor()
       {
          return motor;
       }
       public void setMotor(String string)
       {
          motor = string;
       }
    }
    

    Pull Up 重構與 Push Down 幾乎相同,當然 Pull Up 是將類成員從一個類中移到其父類中,而不是子類中。如果您稍后改變主意,決定還是把 motor 移回到 Vehicle 類中,那么您也許就會用到這種重構。同樣需要提醒您,一定要確認您是否選擇了所有必需的成員。

    Automobile 類中具有成員 motor,這意味著您如果創建另一個子類,比方說 Bus ,您就還需要將 motor (及其相關方法)加入到 Bus 類中。有一種方法可以表示這種關系,即創建一個名為 Motorized 的接口, AutomobileBus 都實現這個接口,但是 RowBoat 不實現。

    創建 Motorized 接口最簡單的方法是在 Automobile 上使用 Extract Interface 重構。為此,您可以在 Outline 視圖中選擇 Automobile ,然后從菜單中選擇 Refactor > Extract Interface。您可以在彈出的對話框中選擇您希望在接口中包含哪些方法,如圖4所示。

    圖 4. 提取 Motorized 接口
    Motorized interface

    點擊 OK 之后,接口就創建好了,如清單8所示。


    清單 8. Motorized 接口
    
    public interface Motorized
    {
       public abstract String getMotor();
       public abstract void setMotor(String string);
    }
    

    同時, Automobile 的類聲明也變成了下面的樣子:

    
    public class Automobile extends Vehicle implements Motorized
    

    使用父類

    本重構工具類型中最后一個是 User Supertyp Where Possible。想象一個用來管理汽車細帳的應用程序。它自始至終都使用 Automobile 類型的對象。如果您想處理所有類型的交通工具,那么您就可以用這種重構將所有對 Automobile 的引用都變成對 Vehicle 的引用(參看圖5)。如果您在代碼中用 instanceof 操作執行了任何類型檢查的話,您將需要決定在這些地方適用的是原先的類還是父類,然后選中第一個選項“Use the selected supertype in 'instanceof' expressions”。

    圖 5. 將 Automobile 改成其父類 Vehicle
    Supertype

    使用父類的需求在 Java 語言中經常出現,特別是在使用了 Factory Method 模式的情況下。這種模式的典型實現方式是創建一個抽象類,其中具有靜態方法 create() ,這個方法返回的是實現了這個抽象類的一個具體對象。如果需創建的具體對象的類型依賴于實現的細節,而調用類對實現細節并不感興趣的情況下,可以使用這一模式。



    回頁首


    改變類內部的代碼

    最大一類重構是實現了類內部代碼重組的重構方法。在所有的重構方法中,只有這類方法允許您引入或者移除中間變量,根據原有方法中的部分代碼創建新方法,以及為屬性創建 getter 和 setter 方法。

    提取與內嵌

    有一些重構方法是以 Extract 這個詞開頭的:Extract Method、Extract Local Variable 以及Extract Constants。第一個 Extract Method 的意思您可能已經猜到了,它根據您選中的代碼創建新的方法。我們以清單8中那個類的 main() 方法為例。它首先取得命令行選項的值,如果有以 -D 開頭的選項,就將其以名-值對的形式存儲在一個 Properties 對象中。


    清單 8. main()
    
    import java.util.Properties;
    import java.util.StringTokenizer;
    public class StartApp
    {
       public static void main(String[] args)
       {
          Properties props = new Properties();
          for (int i= 0; i < args.length; i++)
          {
             if(args[i].startsWith("-D"))
             {
               String s = args[i].substring(2);
               StringTokenizer st = new StringTokenizer(s, "=");
                if(st.countTokens() == 2)
                {
                  props.setProperty(st.nextToken(), st.nextToken());
                }
             }
          }
          //continue...
       }
    }
    

    將一部分代碼從一個方法中取出并放進另一個方法中的原因主要有兩種。第一種原因是這個方法太長,并且完成了兩個以上邏輯上截然不同的操作。(我們不知道上面那個 main() 方法還要處理哪些東西,但是從現在掌握的證據來看,這不是從其中提取出一個方法的理由。)另一種原因是有一段邏輯上清晰的代碼,這段代碼可以被其他方法重用。比方說在某些時候,您發現自己在很多不同的方法中都重復編寫了相同的幾行代碼。那就有可能是需要重構的原因了,不過除非真的需要重用這部分代碼,否則您很可能并不會執行重構。

    假設您還需要在另外一個地方解析名-值對,并將其放在 Properties 對象中,那么您可以將包含 StringTokenizer 聲明和下面的 if 語句的這段代碼抽取出來。為此,您可以高亮選中這段代碼,然后從菜單中選擇 Refactor > Extract Method。您需要輸入方法名稱,這里輸入 addProperty ,然后驗證這個方法的兩個參數, Properties prop Strings 。清單9顯示由 Eclipse 提取了 addProp() 方法之后類的情況。


    清單 9. 提取出來的 addProp()
    
    import java.util.Properties;
    import java.util.StringTokenizer;
    public class Extract
    {
       public static void main(String[] args)
       {
          Properties props = new Properties();
          for (int i = 0; i < args.length; i++)
          {
             if (args[i].startsWith("-D"))
             {
                String s = args[i].substring(2);
                addProp(props, s);
             }
          }
       }
       private static void addProp(Properties props, String s)
       {
          StringTokenizer st = new StringTokenizer(s, "=");
          if (st.countTokens() == 2)
          {
             props.setProperty(st.nextToken(), st.nextToken());
          }
       }
    }
    

    Extract Local Variable 重構取出一段被直接使用的表達式,然后將這個表達式首先賦值給一個局部變量。然后在原先使用那個表達式的地方使用這個變量。比方說,在上面的方法中,您可以高亮選中對 st.nextToken() 的第一次調用,然后選擇 Refactor > Extract Local Variable。您將被提示輸入一個變量名稱,這里輸入 key 。請注意,這里有一個將被選中表達式所有出現的地方都替換成新變量的引用的選項。這個選項通常是適用的,但是對這里的 nextToken() 方法不適用,因為這個方法(顯然)在每一次調用的時候都返回不同的值。確認這個選項未被選中。參見圖6。

    圖 6. 不全部替換所選的表達式
    Extract variable

    接下來,在第二次調用 st.nextToken() 的地方重復進行重構,這一次調用的是一個新的局部變量 value 。清單10顯示了這兩次重構之后代碼的情形。


    清單 10. 重構之后的代碼
    
    private static void addProp(Properties props, String s)
       {
         StringTokenizer st = new StringTokenizer(s, "=");
          if(st.countTokens() == 2)
          {
             String key = st.nextToken();
             String value = st.nextToken();
            props.setProperty(key, value);
          }
       }
    

    用這種方式引入變量有幾點好處。首先,通過為表達式提供有意義的名稱,可以使得代碼執行的任務更加清晰。第二,代碼調試變得更容易,因為我們可以很容易地檢查表達式返回的值。最后,在可以用一個變量替換同一表達式的多個實例的情況下,效率將大大提高。

    Extract Constant 與 Extract Local Variable 相似,但是您必須選擇靜態常量表達式,重構工具將會把它轉換成靜態的 final 常量。這在將硬編碼的數字和字符串從代碼中去除的時候非常有用。比方說,在上面的代碼中我們用“-D”這一命令行選項來定義名-值對。先將“-D”高亮選中,選擇 Refactor > Extract Constant,然后輸入 DEFINE 作為常量的名稱。重構之后的代碼如清單11所示:


    清單 11. 重構之后的代碼
    
    public class Extract
    {
       private static final String DEFINE = "-D";
       public static void main(String[] args)
       {
          Properties props = new Properties();
          for (int i = 0; i < args.length; i++)
          {
             if (args[i].startsWith(DEFINE))
             {
                String s = args[i].substring(2);
                addProp(props, s);
             }
          }
       }
       // ...
    

    對于每一種 Extract... 類的重構,都存在對應的 Inline... 重構,執行與之相反的操作。比方說,如果您高亮選中上面代碼中的變量 s,選擇 Refactor > Inline...,然后點擊 OK,Eclipse 就會在調用 addProp() 的時候直接使用 args[i].substring(2) 這個表達式,如下所示:

            if(args[i].startsWith(DEFINE))
             {
                addProp(props,args[i].substring(2));
             }

    這樣比使用臨時變量效率更高,代碼也變得更加簡要,至于這樣的代碼是易讀還是含混,就取決于您的觀點了。不過一般說來,這樣的內嵌重構沒什么值得推薦的地方。

    您可以按照用內嵌表達式替換變量的相同方法,高亮選中方法名,或者靜態 final 常量,然后從菜單中選擇 Refactor > Inline...,Eclipse 就會用方法的代碼替換方法調用,或者用常量的值替換對常量的引用。

    封裝屬性

    通常我們認為將對象的內部結構暴露出來是一種不好的做法。這也正是 Vehicle 類及其子類都具有 private 或者 protected 屬性,而用 public setter 和 getter 方法來訪問屬性的原因。這些方法可以用兩種不同的方式自動生成。

    第一種生成這些方法的方式是使用 Source > Generate Getter and Setter 菜單。這將會顯示一個對話框,其中包含所有尚未存在的 getter 和 setter 方法。不過因為這種方式沒有用新方法更新對這些屬性的引用,所以并不算是重構;必要的時候,您必須自己完成更新引用的工作。這種方式可以節約很多時間,但是最好是在一開始創建類的時候,或者是向類中加入新屬性的時候使用,因為這些時候還不存在對屬性的引用,所以不需要再修改其他代碼。

    第二種生成 getter 和 setter 方法的方式是選中某個屬性,然后從菜單中選擇 Refactor > Encapsulate Field。這種方式一次只能為一個屬性生成 getter 和 setter 方法,不過它與 Source > Generate Getter and Setter 相反,可以將對這個屬性的引用改變成對新方法的調用。

    例如,我們可以先創建一個新的簡版 Automobile 類,如清單12所示。


    清單 12. 簡單的 Automobile 類
    
    public class Automobile extends Vehicle
    {
       public String make;
       public String model;
    }
    

    接下來,創建一個類實例化了 Automobile 的類,并直接訪問 make 屬性,如清單13所示。


    清單 13. 實例化 Automobile
    
    public class AutomobileTest
    {
       public void race()
       {
          Automobilecar1 = new Automobile();
          car1.make= "Austin Healy";
          car1.model= "Sprite";
          // ...
       }
    }

    現在封裝 make 屬性。先高亮選中屬性名稱,然后選擇 Refactor > Encapsulate Field。在彈出的對話框中輸入 getter 和 setter 方法的名稱——如您所料,缺省的方法名稱分別是 getMake() 和 setMake()。您也可以選擇與這個屬性處在同一個類中的方法是繼續直接訪問該屬性,還是像其他類那樣改用這些訪問方法。(有一些人非常傾向于使用這兩種方式的某一種,不過碰巧在這種情況下您選擇哪一種方式都沒有區別,因為 Automobile 中沒有對 make 屬性的引用。)

    圖7. 封裝屬性
    Encapsulating a field

    點擊 OK之后, Automobile 類中的 make 屬性就變成了私有屬性,也同時具有了 getMake() setMake() 方法。

    >
    清單 14. 經過重構的 Automobile 類
    public class Automobile extends Vehicle
    {
       private String make;
       public String model;
    
       public void setMake(String make)
       {
          this.make = make;
       }
    
       public String getMake()
       {
          return make;
       }
    }
    

    AutomobileTest 類也要進行更新,以便使用新的訪問方法,如清單15所示。


    >清單 15. AutomobileTest 類
    
    public class AutomobileTest
    {
       public void race()
       {
          Automobilecar1 = new Automobile();
          car1.setMake("Austin Healy");
          car1.model= "Sprite";
          // ...
       }
    }

    改變方法的簽名

    本文介紹的最后一個重構方法也是最難以使用的方法:Change Method Signature(改變方法的簽名)。這種方法的功能顯而易見——改變方法的參數、可見性以及返回值的類型。而進行這樣的改變對于調用這個方法的其他方法或者代碼會產生什么影響,就不是那么顯而易見了。這么也沒有什么魔方。如果代碼的改變在被重構的方法內部引發了問題——變量未定義,或者類型不匹配——重構操作將對這些問題進行標記。您可以選擇是接受重構,稍后改正這些問題,還是取消重構。如果這種重構在其他的方法中引發問題,就直接忽略這些問題,您必須在重構之后親自修改。

    為澄清這一點,考慮清單16中列出的類和方法。


    清單 16. MethodSigExample 類
    
    public class MethodSigExample
    {
       public int test(String s, int i)
       {
          int x = i + s.length();
          return x;
       }
    }
    

    上面這個類中的 test() 方法被另一個類中的方法調用,如清單17所示。


    清單 17. callTest 方法
    
    public void callTest()
       {
         MethodSigExample eg = new MethodSigExample();
         int r = eg.test("hello", 10);
       }

    在第一個類中高亮選中 test ,然后選擇 Refactor > Change Method Signature。您將看到如圖8所示的對話框。

    圖 8. Change Method Signature 選項
    Change Method Signature options

    第一個選項是改變該方法的可見性。在本例中,將其改變為 protected 或者 private,這樣第二個類的 callTest() 方法就不能訪問這個方法了。(如果這兩個類在不同的包中,將訪問方法設為缺省值也會引起這樣的問題。) Eclipse 在進行重構的時候不會將這些問題標出,您只有自己選擇適當的值。

    下面一個選項是改變返回值類型。如果將返回值改為 float ,這不會被標記成錯誤,因為 test() 方法返回語句中的 int 會自動轉換成 float 。即便如此,在第二個類的 callTest() 方法中也會引起問題,因為 float 不能轉換成 int 。您需要將 test() 的返回值改為 int ,或者是將 callTest() 中的 r 改為 float

    如果將第一個參數的類型從 String 變成 int ,那么也得考慮相同的問題。在重構的過程中這些問題將會被標出,因為它們會在被重構的方法內部引起問題: int 不具有方法 length() 。然而如果將其變成 StringBuffer ,問題就不會標記出來,因為 StringBuffer 的確具有方法 length() 。當然這會在 callTest() 方法中引起問題,因為它在調用 test() 的時候還是把一個 String 傳遞進去了。

    前面提到過,在重構引發了問題的情況下,不管問題是否被標出,您都可以一個一個地修正這些問題,以繼續下去。還有一種方法,就是先行修改這些錯誤。如果您打算刪除不再需要的參數 i ,那么可以先從要進行重構的方法中刪除對它的引用。這樣刪除參數的過程就更加順利了。

    最后一件需要解釋的事情是 Default Value 選項。這一選項值僅適用于將參數加入方法簽名中的情況。比方說,如果我們加入了一個類型為 String 的參數,參數名為 n ,其缺省值為 world ,那么在 callTest() 方法中調用 test() 的代碼就變成下面的樣子:

          
             public void callTest()
       {
          MethodSigExample eg = new MethodSigExample();
          int r = eg.test("hello", 10, "world");
       }
    

    在這場有關 Change Method Signature 重構的看似可怕的討論中,我們并沒有隱藏其中的問題,但卻一直沒有提到,這種重構其實是非常強大的工具,它可以節約很多時間,通常您必須進行仔細的計劃才能成功地使用它。



    回頁首


    結束語

    Eclipse 提供的工具使重構變得簡單,熟悉這些工具將有助于您提高效率。敏捷開發方法采用迭代方式增加程序特性,因此需要依賴于重構技術來改變和擴展程序的設計。但即便您并沒有使用要求進行正式重構的方法,Eclipse 的重構工具還是可以在進行一般的代碼修改時提供節約時間的方法。如果您花些時間熟悉這些工具,那么當出現可以利用它們的情況時,您就能意識到所花費的時間是值得的。



    回頁首


    參考資料

    • 您可以參閱本文在 developerWorks 全球站點上的 英文原文.

    • 有關重構的核心著作是 Refactoring: Improving the Design of Existing Code, 作者 Martin Fowler、Kent Beck、John Brant、William Opdyke 和 Don Roberts(Addison-Wesley,1999年)。

    • 重構是一種正在發展的方法,在 Eclipse In Action: A Guide for Java Developers (Manning, 2003年)一書中,作者 David Gallardo,Ed Burnette 以及 Robert McGovern 從在 Eclipse 中設計和開發項目的角度討論了這一話題。

    • 模式(如本文中提到的 Factory Method 模式)是理解和討論面向對象設計的重要工具。這方面的經典著作是 Design Patterns: Elements of Reusable Object-Oriented Software,作者為 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides (Addison-Wesley,1995年)。

    • Design Patterns 中的例子是用 C++ 寫成的,這對于 Java 程序員是不小的障礙;Mark Grand 所著的 Patterns in Java, Volume One: A Catalog of Reusable Design Patterns Illustrated with UML(Wiley,1998年)將模式翻譯成了 Java 語言。

    • 有關敏捷編程的一個變種,請參看 Kent Beck 所著的 Extreme Programming Explained: Embrace Change(Addison-Wesley,1999年)
    Web 站點 developerWorks 上的文章與教程

    回頁首


    關于作者

    David Gallardo 是 Studio B 上的一名作家,他是一名獨立軟件顧問和作家,專長為軟件國際化、Java Web 應用程序和數據庫開發。他成為專業軟件工程師已經有十五年了,他擁有許多操作系統、編程語言和網絡協議的經驗。他最近在一家 BtoB 電子商務公司 TradeAccess, Inc 領導數據庫和國際化開發。在這之前,他是 Lotus Development Corporation 的 International Product Development 組中的高級工程師,負責為 Lotus 產品(包括 Domino)提供 Unicode 和國際語言支持的跨平臺庫的開發。David 是 Eclipse In Action: A Guide for Java Developers(2003年)一書的合著者??梢酝ㄟ^ david@gallardo.org 與 David 聯系。

    posted @ 2006-01-17 15:28 只牽這只狗 閱讀(335) | 評論 (0)編輯 收藏

    原來自己的生日已經過了......不知不覺的過了...........
    posted @ 2006-01-10 09:29 只牽這只狗 閱讀(200) | 評論 (0)編輯 收藏

    男人25歲前不會明白的道理

        

      1、男人是社會的主體,不管你信或不信。所以男人應該有種責任感。
       
      2、25歲之前,請記得,愛情通常是假的,或者不是你所想象的那樣純潔和永遠。如果你過了25歲,那么你應該懂得這個道理。
       
      3、吃飯7成飽最舒服。對待女友最多也請你保持在7成。
       
      4、30歲之前請愛惜自己的身體,前30年你找病,后30年病找你。如果你過了30歲,你自然也會懂得這個道理。
       
      5、事業遠比愛情重要。如果說事業都不能永恒,那么愛情只能算是曇花一現。
       
      6、不要輕易接受追求你的女孩。女追男隔層紗,如果你很容易就陷進去,你會發現你會錯過很多東西,失去很多東西。
       
      7、請你相信,能用錢解決的問題,都不是問題。如果你認為錢索王道,有錢有女人,沒錢沒女人,那么,女人不是問題。
       
      8、請永遠積極向上。每個男人都有他可愛的地方,但是不可愛的地方只有:不積極面對生活。
       
      9、不要連續2次讓同一個女人受到傷害。好馬不吃回頭草是有道理的。如果認真考慮過該分手,那么請不要做任何舍不得的行動。
       
      10、如果你和你前女友能做朋友,那么你要問自己:為什么?如果分手后還是朋友,那么只有2個可能:你們當初都只是玩玩而已,沒付出彼此最真的感情;或者:必定有個人是在默默的付出無怨無悔!
       
      11、永遠不要太相信女人在戀愛時的甜言蜜語。都說女人愛聽甜言蜜語,其實,男人更喜歡。
       
      12、請不要為自己的相貌或者身高過分擔心和自卑。人是動物,但是區別于動物。先天條件并不是阻擋你好好生活的借口。人的心靈遠勝于相貌,請相信這點。如果有人以相貌取人,那么你也沒必要太在意。因為他從某種意義來講,只是只動物,你會跟動物慪氣嗎?
       
      13、失戀時,只有2種可能,要么你愛她她不愛你,或者相反。那么,當你愛的人不再愛你,或者從來沒愛過你時,你沒有遺憾,因為你失去的只是一個不愛你的人。
       
      14、請不要欺騙善良的女孩。這個世界上善良的女孩太少。
       
      15、不能偏激的認為金錢萬能,至少,金錢治不好艾滋病。
       
      16、請一定要有自信。你就是一道風景,沒必要在別人風景里面仰視。
       
      17、受到再大的打擊,只要生命還在,請相信每天的太陽都是新的。
       
      18、愛情永遠不可能是天平。你想在愛情里幸福就要舍得傷心。
       
      19、如果你喜歡一個她認為別人應該對她好的MM,請盡早放棄。沒有人是應該對一個人好的。如果她不明白這個道理,也就是她根本不懂得珍惜。
       
      20、不要因為寂寞而“找”GF,寂寞的男人請要學會品味寂寞。請記住:即使寂寞,遠方黑暗的夜空下,一定有人和你一樣,寂寞的人不同,仰望的星空卻是唯一。
       
      21、任何事沒有永遠,也別問怎樣才能永遠。生活有很多無奈,請盡量充實自己,充實生活。請善待生活。
       
      End、男人有很多無奈,生活很累,但是因為生活才有意義。當你以為你一無所有時,你至少還有時間,時間能撫平一切創傷。所以請不要流淚。

    posted @ 2006-01-10 09:12 只牽這只狗 閱讀(234) | 評論 (0)編輯 收藏

    也許明天會更好.......

    posted @ 2006-01-10 08:51 只牽這只狗 閱讀(219) | 評論 (0)編輯 收藏

    摘要:

    雖然大部分開發人員在過去使用過XMLHttp或者使用Iframe來加載數據,但僅到現在我們才看到傳統的開發人員和公司開始采用這些技術。就像新的編程語言或模型伴隨著更多的痛苦,開發人員需要學習新的技巧及如何最好利用這些新技術。這篇文章講述了開發人員使用AJAX需要使用的工具和技術。

    文章工具

    作者:Andrew Thompson;xMatrix (他的blog:http://blog.matrix.org.cn/page/xMatrix)
    原文地址:http://www.javaworld.com/javaworld/jw-10-2005/jw-1017-ajax.html
    中文地址:http://www.matrix.org.cn/resource/article/44/44116_AJAX.html
    關鍵詞: AJAX

    AJAX開發者的最新工具和技術

    基于XML的異步JavaScript,簡稱AJAX,是當前Web創新(稱為Web2.0)中的一個王冠。感謝組成AJAX的各種技術,Web應用的交互如Flickr, Backpack和Google在這方面已經有質的飛躍。這個術語源自描述從基于網頁的Web應用到基于數據的應用的轉換。在基于數據的應用中,用戶需求的數據如聯系人列表,可以從獨立于實際網頁的服務端取得并且可以被動態地寫入網頁中,給緩慢的Web應用體驗著色使之像桌面應用一樣。

    雖然大部分開發人員在過去使用過XMLHttp或者使用Iframe來加載數據,但僅到現在我們才看到傳統的開發人員和公司開始采用這些技術。就像新的編程語言或模型伴隨著更多的痛苦,開發人員需要學習新的技巧及如何最好利用這些新技術。這篇文章講述了開發人員使用AJAX枰褂玫墓ぞ吆圖際酢?lt;br />
    AJAX模式
    許多重要的技術和AJAX開發模式可以從現有的知識中獲取。例如,在一個發送請求到服務端的應用中,必須包含請求順序、優先級、超時響應、錯誤處理及回調,其中許多元素已經在Web服務中包含了,就像現在的SOA。AJAX開發人員擁有一個完整的系統架構知識。同時,隨著技術的成熟還會有許多地方需要改進,特別是UI部分的易用性。

    AJAX開發與傳統的CS開發有很大的不同。這些不同引入了新的編程問題,最大的問題在于易用性。由于AJAX依賴瀏覽器的JavaScript和XML,瀏覽器的兼容性和支持的標準也變得和JavaScript的運行時性能一樣重要了。這些問題中的大部分來源于瀏覽器、服務器和技術的組合,因此必須理解如何才能最好的使用這些技術。

    綜合各種變化的技術和強耦合的客戶服務端環境,AJAX提出了一種新的開發方式。AJAX開發人員必須理解傳統的MVC架構,這限制了應用層次之間的邊界。同時,開發人員還需要考慮CS環境的外部和使用AJAX技術來重定型MVC邊界。最重要的是,AJAX開發人員必須禁止以頁面集合的方式來考慮Web應用而需要將其認為是單個頁面。一旦UI設計與服務架構之間的范圍被嚴格區分開來后,開發人員就需要更新和變化的技術集合了。


    時刻想著用戶
    AJAX的最大機遇在于用戶體驗。在使應用更快響應和創新的過程中,定義Web應用的規則正在被重寫;因此開發人員必須更注重用戶?,F在用戶已經逐漸習慣如何使用Web應用了。例如用戶通常希望每一次按鈕點擊會導致幾秒的延遲和屏幕刷新,但AJAX正在打破這種長時間的狀況。因此用戶需要重新體驗按鈕點擊的響應了。

    可用性是AJAX另人激動的地方而且已經產生了幾種新穎的技術。其中最引人注目的是一種稱為“黃色隱出”的技術,他在數據更新之前時將用戶界面變為黃色,更新完成后立刻恢復原來的顏色。AJAX開發人員將用戶從Web應用的負載中解放出來;小心地利用AJAX提供的豐富接口,不久桌面開發人員會發現AJAX是他們的方向。


    幾種工具和技術
    隨著AJAX迅速地引人注目起來,我想開發人員對這種技術的期待也迅速地增加。就像任何新技術,AJAX的興旺也需要一整個開發工具/編程語言及相關技術系統來支撐。

    JavaScript
    如名字所示AJAX的概念中最重要而最被忽視的是他也是一種JavaScript編程語言。JavaScript是一種粘合劑使AJAX應用的各部分集成在一起。在大部分時間,JavaScript通常被服務端開發人員認為是一種企業級應用不需要使用的東西應該盡力避免。這種觀點來來自以前編寫JavaScript代碼的經歷:繁雜而又易出錯的語言。類似的,他也被認為將應用邏輯任意地散布在服務端和客戶端中,這使得問題很難被發現而且代碼很難重用。在AJAX中JavaScript主要被用來傳遞用戶界面上的數據到服務端并返回結果。XMLHttpRequest對象用來響應通過HTTP傳遞的數據,一旦數據返回到客戶端就可以立刻使用DOM將數據放到網面上。

    XMLHttpRequest
    XMLHttpRequest對象在大部分瀏覽器上已經實現而且擁有一個簡單的接口允許數據從客戶端傳遞到服務端,但并不會打斷用戶當前的操作。使用XMLHttpRequest傳送的數據可以是任何格式,雖然從名字上建議是XML格式的數據。

    開發人員應該已經熟悉了許多其他XML相關的技術。XPath可以訪問XML文檔中的數據,但理解XML DOM是必須的。類似的,XSLT是最簡單而快速的從XML數據生成HTML或XML的方式。許多開發人員已經熟悉Xpath和XSLT,因此AJAX選擇XML作為數據交換格式有意義的。XSLT可以被用在客戶端和服務端,他能夠減少大量的用JavaScript編寫的應用邏輯。

    CSS
    為了正確的瀏覽AJAX應用,CSS是一種AJAX開發人員所需要的重要武器。CSS提供了從內容中分離應用樣式和設計的機制。雖然CSS在AJAX應用中扮演至關重要的角色,但他也是構建創建跨瀏覽器應用的一大阻礙,因為不同的瀏覽器廠商支持各種不同的CSS級別。

    服務器端
    但不像在客戶端,在服務端AJAX應用還是使用建立在如Java,.Net和PHP語言基礎上機制;并沒有改變這個領域中的主要方式。
    既然如此,我們對Ruby on Rails框架的興趣也就迅速增加了。在一年多前,Ruby on Rails已經吸引了大量開發人員基于其強大功能來構建Web和AJAX應用。雖然目前還有很多快速應用開發工具存在,Ruby on Rails看起來已經儲備了簡化構建AJAX應用的能力。

    開發工具
    在實際構建AJAX應用中,你需要的不只是文本編輯器。既然是JavaScript非編譯的,他可以容易地編寫和運行在瀏覽器中;然而,許多工具提供了有用的擴展如語法高亮和智能完成。

    不同的IDE提供了對JavaScript支持的不同等級。來自JetBrains的IntelliJ IDEA是一個用來JavaScript開發的更好的IDE,雖然許多開發人員也喜歡Microsoft’s Visual Studio產品(允諾會在最新的版本中改善對AJAX的支持)。Eclipse包含了兩個免費的JavaScript編輯器插件和一個商業的來自ActiveStat的Komodo IDE。

    另一個JavaScript和AJAX開發中的問題是調試困難。不同的瀏覽器提供不同的通常是隱藏的運行時錯誤信息,而JavaScript的缺陷如雙重變量賦值(通常是由于缺少數據類型)使得調試更加困難。在AJAX的開發中,調試就更復雜了,因為其需要標識究竟是客戶端還是服務端產生的錯誤。在過去,JavaScript調試的方法是刪除所有代碼然后一行行的增加直到錯誤出現?,F在,更多開發人員回到為IE準備的Microsoft Script Debugger和為Mozilla瀏覽器準備的Venkman。


    瀏覽器兼容性
    JavaScript編程的最大問題來自不同的瀏覽器對各種技術和標準的支持。構建一個運行在不同瀏覽器(如IE和火狐)是一個困難的任務。因此幾種AJAX JavaScript框架或者生成基于服務端邏輯或標記庫的JavaScript,或者提供符合跨瀏覽器AJAX開發的客戶端JavaScript庫。一些流行的框架包括:AJAX.Net, Backbase, Bitkraft, Django, DOJO, DWR, MochiKit, Prototype, Rico, Sajax, Sarissa, and Script.aculo.us.

    這些框架給開發人員更多的空間使得他們不需要擔心跨瀏覽器的問題。雖然這些框架提升了開發人員構建應用的能力,但由于廠商已經開發了更細節的用戶界面的打包組件解決方案,因此在AJAX組件市場中需要考慮一些其他因素。例如提供通用用戶界面的組件如組合框和數據柵格的幾個廠商,都可以被用來在應用中創建良好的通過類似電子數據表方式來查看和編輯數據的體驗。但這些組件不僅是封裝了組件的用戶界面而且包括與服務端數據的通訊方式,這些組件通常使用基于標記方式來實現如ASP.Net或JSF控件。


    展望
    最近IE和火狐之間的瀏覽器之爭變得火熱起來,因此AJAX開發人員需要足夠敏捷的作出反應。關鍵點在一些問題如CSS或XML,雖然各種瀏覽器形成采用最新標準的不同陣營(如Mozilla擁抱SVG和E4X標準及在最新火狐BETA版本中使用XUL,而微軟使用自己的XAML技術)。所有這些技術代表當前AJAX主流JavaScript和XML的市場方向改變。
    總的來說,AJAX開發人員必須盡快地跟進最新的技術并利用高產的工具集。成功的AJAX開發人員還需要留心他們的使用者以避免將任何問題擴大化。并且AJAX開發人員還需要持續地創新來創建增強Web應用易用性的新方法。


    作者
    Dave Johnson是加拿大Vancouver一家軟件咨詢公司eBusiness Applications創始人和傳道者,擁有七年以上的XML相關工作經驗。


    Resources
    ? AJAX開發人員的編譯模式:http://www.ajaxpatterns.org
    ?  XMLHttpRequest教程:“動態網頁接口”:http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
    ? JavaScript性能基準:http://blogs.ebusiness-apps.com/dave/?p=14
    ? AJAX資源:http://www.ajaxmatters.com
    ? JavaScript規范:http://www.ecma-international.org/publications/standards/Ecma-262.htm
    ? 介紹JavaScript對象標識:http://www.crockford.com/JSON/index.html
    ?  Mozilla 的Venkman JavaScript調試器:http://www.mozilla.org/projects/venkman/
    ?  XML DOM參考:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
    xmlsdk/html/e9da2722-7879-4e48-869c-7f16714e2824.asp
    ? Microsoft Dynamic HTML reference: http://msdn.microsoft.com/library/default.asp?url=/
    workshop/author/dhtml/reference/dhtml_reference_entry.asp
    ? Gecko DOM Reference: http://www.mozilla.org/docs/dom/domref/
    ? "“移植IE應用到Mozilla”
    http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
    ? Mozilla XUL reference:
    http://www.xulplanet.com/
    ? Microsoft XAML reference:
    http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/
    en-us/wcp_conceptual/html/0ff5f36e-dd84-44d1-aa3e-5bb4f147b169.asp?frame=true
    ? James Jesses Garret introduced the term AJAX in his article "AJAX: A New Approach to Web Applications," (Adaptive Path, February 2005): “AJAX:新的網頁應用開發方式”
    http://www.adaptivepath.com/publications/essays/archives/000385.php
    ? JetBrains IntelliJ IDEA:
    http://www.jetbrains.com/
    ? Microsoft Visual Studio:
    http://msdn.microsoft.com/vstudio/
    ? JSEditor:
    http://jseditor.sourceforge.net/
    ? JSEclipse:
    http://www.interaktonline.com/Products/Eclipse/JSEclipse/Overview/
    ? ActiveState Komodo:
    http://www.activestate.com/Products/Komodo/
    ? XHTML:
    http://www.w3.org/TR/xhtml1/
    ? Document Object Model:
    http://www.w3.org/DOM/
    ? Cascading Style Sheets:
    http://www.w3.org/Style/CSS/
    ? Extensible Stylesheet Language:
    http://www.w3.org/Style/XSL/
    ? XForms:
    http://www.w3.org/MarkUp/Forms/
    ? Scaling Vector Graphics:
    http://www.w3.org/Graphics/SVG/
    ? XPath:
    http://www.w3.org/TR/xpath
    ? AJAX.Net:
    http://ajax.schwarz-interactive.de/csharpsample/default.aspx
    ? Backbase:
    http://www.backbase.com
    ? Bitkraft:
    http://www.tiggrbitz.com/
    ? Django:
    http://www.djangoproject.com/
    ? Dojo:
    http://www.dojotoolkit.org/
    ? DWR (Direct Web Reporting):
    http://getahead.ltd.uk/dwr/
    ? MochiKit:
    http://mochikit.com/
    ? Prototype:
    http://prototype.conio.net/
    ? Rico:
    http://openrico.org/rico/home.page
    ? Sajax:
    http://www.modernmethod.com/sajax/
    ? Sarissa:
    http://sarissa.sourceforge.net/doc/
    ? Script.aculo.us:
    http://script.aculo.us/
    ? Ruby on Rails:
    http://www.rubyonrails.org/
    ? For more on AJAX and DWR, read "AJAX Made Simple with DWR," Cloves Carneiro Jr. (JavaWorld, June 2005): 關于AJAX和DWR,請閱讀“AJAX使用DWR更簡單”
    http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr.html
    ? For more articles on Java development tools, browse the Development Tools section of JavaWorld’s Topical Index: 更多Java開發工具的文章,請瀏覽JavaWorld的開發工具部分索引頁
    http://www.javaworld.com/channel_content/jw-tools-index.shtml
    ? For more articles on XML, browse the Java and XML section of JavaWorld’s Topical Index: 更多XML的文章,請瀏覽JavaWorld的Java和XML部分索引頁
    http://www.javaworld.com/channel_content/jw-xml-index.shtml
    ? For more articles on UI design, browse the User Interface Design section of JavaWorld’s Topical Index: 更多UI設計的文章,請瀏覽JavaWorld的UI設計部分索引頁
    http://www.javaworld.com/channel_content/jw-ui-index.shtml


    原文地址:
    posted @ 2006-01-04 10:53 只牽這只狗 閱讀(210) | 評論 (0)編輯 收藏

    2.3 業務邏輯層設計

      2.3.1 動態加載技術

      如果一次性獲取完整的先序樹,構造成xml提供給JavaScript解析,數據量越大,消耗的資源越多,客戶端響應延遲時間就越長,因此對于大數據量的樹,采用動態加載方式,即每次單擊“+”圖片時,判斷是否已加載子節點數據,如果未加載則通過Ajax的XMLHTTP組件XMLHTTPRequest對象異步發送請求,連接服務器執行SQL 語句“select * from tree_class where parent = ?order by classcode ”獲取節點數據。相關JavaScript 代碼如下:

    /*判斷是否已經加載數據,未加載則訪問服務器加載數據*/

    dhtmlTree.prototype.Loading=function(pObject){
     if(((pObject.XMLload==0)&&(this.XMLsource))&&(!this.XMLloading)){
      pObject.XMLload=1;
      this.loadXML(this.XMLsource+getUrlSymbol(this.XMLsource)+"id="+escape(pObject.id));
     }
    }
    dtmlXMLObject.prototype.loadXML=function(url){//加載數據
     try {
      this.xmlDoc = new XMLHttpRequest();
      /*通過GET方法異步連接到 url 加載數據*/
      this.xmlDoc.open("GET", url,true);//true:異步;false:同步
      this.xmlDoc.send(null);
     } catch(e){
      this.xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");//使用IE
      this.xmlDoc.open("GET", url,true);//true:異步;false:同步
      this.xmlDoc.send(null);
     }
     return this.xmlDoc.responseXML;
    }

      每次只取同一個父節點ParentId的子節點序列,按XML格式封裝成樹的文檔結構,例如:

    <tree id="0">
    <leaf child=”1" name="國防科技大學" id="1" im0="leaf.gif" im1="folderOpen.gif" im2=" folderClosed.gif"/>
    </tree>

      提供給JavaScript的dhtmlTreeObject.prototype.insertItem()解析并組織好html輸出節點;其中 child:1表示有子節點,0表示沒有子節點;im0表示沒有子節點時的圖標;im1表示有子節點并且打開節點時的圖標;im2表示有子節點并且關閉時的圖標;所以還可以在構造XML時自定義圖標。

      2.3.2 樹型結構的構造

      從數據庫中返回的是有序的先序樹,而XML是完整的樹型結構文檔,所以將樹型數據構造成預定義的XML格式,只需從根節點開始,遍歷一遍樹,即可將樹全部生成。相關JavaScript代碼如下:

    /*動態加載樹的構造方法*/

    dtmlXMLObject.prototype.constructTree=function(){

    //采用動態加載時獲取的xml數據,解析樹型數據

    var node=this.XMLLoader.getXMLTopNode("tree");

    var parentId=node.getAttribute("id");

    for(var i=0;i<node.childNodes.length;i++) { //逐個解析xml文件的leaf節點

     if((node.childNodes[i].nodeType==1)&&(node.childNodes[i].tagName == "leaf")){
      var name=node.childNodes[i].getAttribute("text");
      …………
      var temp=dhtmlObject.a0Find(parentId);//獲取父節點對象
      temp.XMLload=1;//已加載
      //構造html輸出節點
      dhtmlObject.insertItem(parentId,cId,name,im0,im1,im2,chd);
      dhtmlObject.addDragger = this;//設置可拖放的對象
     };
    }

      2.3.3 樹型結構的維護

      在維護樹型結構表時,刪除節點較為簡單,SQL 語句為: "delete from tree_class where classcode like′"+ classcode +"%′",即可將其節點和孩子一并刪除;增加節點時,分為前插、后插、和插入子節點三種情況,前兩種情況需要更新遞歸更新類別代碼,后者只需找到父節點的孩子的最大類別代碼加1 后,作為增加節點的類別代碼;通過拖放來改變樹的結構時,只需將拖動節點的parentId更新為目標節點的Classid即可,對應的SQL語句為:"update tree_class set parentId = "+ classidTo+" where classid = "+ classidFrom。

      3、效率分析

      對于樹的存儲一般有兩種形式:二維表和鏈表,遍歷方式一般也有深度遍歷和廣度遍歷兩種方式,遍歷的時間復雜度都是O( n )。用二維表存儲時,在內存中用數組的下標能準確定位節點的父節點、兄弟節點所在的數組下標。數據庫中節點的定位也是準確的,但是將節點信息從數據庫中讀到內存中時,如果無法通過內存數組下標定位節點信息,那么就必須遍歷一遍尋找一個節點,n 個節點中尋找一個節點的時間是O(n/2),n 個節點排序的時間復雜度將是O( n 2/2),這也是一般實現的B/S 模式的樹結構效率低下的原因。本方案采用字典序編號方案,使得從數據庫中取得的樹是已經排序的,直接遍歷生成客戶頁面程序,時間復雜度為O( n )。

      4、結 論

      本文討論了基于Ajax的動態樹型結構的實現方案,支持無刷新動態維護樹的節點信息,支持拖放節點改變樹的節點結構以及次序;同時采用數據庫存儲節點信息,保證了該方案有一定的通用性,此外結合XML描述樹的節點信息,使得任何按本方案預定的xml文檔描述的信息都可以通過樹來展現。本方案已經應用在我校的數字迎新系統以及老百姓大藥房信息系統中。

    posted @ 2005-12-30 08:32 只牽這只狗 閱讀(393) | 評論 (0)編輯 收藏

    2.1 表示層實現

      類似Windows資源管理器的文件夾模式,節點的圖片樣式如表1所示。對于每個節點的DHTML 代碼,需要包含節點的位置、前導圖片、樣式、針對該節點的其他操作等。同時為了節點顯示的連貫性,還需一些前導圖片。

      表1 樹節點的前的圖片樣式表

     對于樹的非葉子節點,圖片和節點信息等,采用一個DIV ( division) 容器包含。DIV 等容器是DHTML 的基礎,使用它可以通過腳本程序對其屬性進行操作,如設置其style 樣式的display 屬性來控制子節點的展開和隱藏。節點的位置、前導圖片、樣式、針對該節點的其他的操作等都放入容器中,例:

    < DIV id =mParentID>
    < IMG align = center border = 0 onclick =″nodeExpand (‘leafid’)″ name = m1Tree src =′Tplus.gif′>
    < IMG align = center border = 0 name = m1Folder src =′folderClosed. gif′> 計算機學院 </p>

      葉子節點無需容器直接輸出即可。

      當點擊某節點前的“ + ”、“ - ”圖片時通過DIV 的style 樣式的display 屬性控制子節點的展開和隱藏。display:“none”(隱藏,不可見),display:“block”(顯示) 。相關JavaScript 代碼如下:

    if (expandChild.style.display = =″none″){
     // 當前為隱藏狀態,執行展開動作
     this.Loading(parentObject);//判斷該分支的數據是否已經加載
     expandChild.style.display =″block″;
    if (para2 = =″last″)
     parentObject.src =″Lminus. gif″; // 最后一個節點
    else
     parentObject.src = ″Tminus. gif″; // 顯示┠
     expandFolder.src = ″folderOpen. gif″;
    }else {
     // 將當前節點的子節點全部隱藏
     expandChild.style.display = ″none″;
     if (para2 = = ″last″)
      parentObject.src = ″Lplus. gif″;
     else
      parentObject.src = ″Tplus. gif″;
      expandFolder.src = ″folderClosed. gif″;
    }

      2.2 樹型表結構設計

      我們以數據庫為載體記錄節點的變化,樹型表結構至少要有以下字段:節點的編號(CLASSID) ,對節點的描述(ClassName),父節點的編號(ParentId),這些是構建樹結構所必須的信息。同時引入節點的類別代碼(ClassCode),節點的級別(ClassLevel),是否葉子節點 (Terminated)等輔助字段,記錄節點次序,實體關系圖如圖3所示。


    圖 3 樹型表結構示意圖

      樹遍歷的時間復雜度是O( n ),但是將樹信息存放到數據庫后,就不能按傳統的方式遍歷樹,必須使用SQL 語句訪問數據庫表的內容,而一次性取的數據量越多,消耗的資源也越多,用戶等待的時間就越長。如果將無序的數據從數據庫中讀出,在服務器端,必須將排序后的樹送到客戶端顯示。因此,最好從數據庫讀出已排好序的樹。

      我們知道,字符串排序是按照字典序形式。結合SQL 語句的特點和樹結構特點,數據庫表中,節點的類別代碼采用多級字符串形式,如AAABBBCCC,從樹根節點開始,每向下一級字符串就增加一級,并且子節點類別代碼以父節點類別代碼開始,再開始本級的類別代碼。同級的節點按照生成的順序編號,如節點類別代碼為AAA 的下一級孩子類別代碼為AAAAAA,AAAAAB 等,AAAAAB 的孩子節點為AAAAABAAA、AAAAABAAB等。每一級編號字符的寬度與實際的應用關聯,如AAA~ZZZ 一級則有263 個節點,如果不夠用再增加一個字符用于編碼。該巧妙的編號方式。使得在執行SQL 語句select * from tree_class order by classcode 后,一次獲得完整的先序.

    原文鏈接:http://www.7dspace.com/doc/44/0512/2005122906292220003.htm

    posted @ 2005-12-30 08:31 只牽這只狗 閱讀(398) | 評論 (0)編輯 收藏

    僅列出標題
    共3頁: 1 2 3 下一頁 
    主站蜘蛛池模板: 亚洲AV无码XXX麻豆艾秋| 男人j进入女人j内部免费网站| 免费一级做a爰片久久毛片潮喷| 一本一道dvd在线观看免费视频| 亚洲成AV人片在线观看ww| 啦啦啦中文在线观看电视剧免费版| 国产亚洲高清在线精品不卡| 亚洲AV中文无码字幕色三| 最近2019中文免费字幕| 精品一区二区三区免费视频| 亚洲乱码一区av春药高潮| 亚洲一区精品中文字幕| 卡1卡2卡3卡4卡5免费视频| 天堂在线免费观看| 亚洲精品无码专区久久久| 波多野结衣中文字幕免费视频| 香蕉国产在线观看免费| 亚洲视频国产精品| 久久夜色精品国产亚洲av| 免费看黄视频网站| 两个人看的www高清免费观看| 日韩亚洲人成在线| 亚洲午夜久久久精品影院| 天堂亚洲免费视频| 性色av无码免费一区二区三区| 99精品免费视频| 黄色毛片视频免费| 亚洲国产区男人本色在线观看| 亚洲色偷偷偷鲁综合| 国产jizzjizz免费看jizz| 国产一卡2卡3卡4卡无卡免费视频| 久久久免费观成人影院| 小说专区亚洲春色校园| 亚洲va在线va天堂va手机| 亚洲AV色香蕉一区二区| 最新国产AV无码专区亚洲 | 亚洲国产一区明星换脸| 国产va精品免费观看| 国产92成人精品视频免费| 精品国产污污免费网站| 精选影视免费在线 |