摘要
開發人員通過各種各樣的方法來嘗試避免單調冗餘的編程。一些編程的規則例如繼承、多態或者設計模型可以協助開發人員避免產生多餘的代碼。不過由於軟體開發方面存在著不確定性,因此這些規則並不能消除代碼維護和重新編寫的需要。在很多時候維護都是不可避免的,只有不能運作的軟體才是從不需要維護的。不過,這篇文章介紹了你可以使用Java的Reflection API的功能來減少單調的代碼編寫,並可以使用活動的代碼產生來克服reflection的限制。
資料配置(由外部的源頭得到資料並且將它裝載到一個Java對象中)可以利用reflection的好處來建立一個可重用的方案。問題是很簡單的:將資料由一個檔案裝入到一個對象的欄位中。現在假設用作資料的目標Java類每星期改變一次?有一個很直接的解決方案,不過你必須不斷地維護載入的過程來反映任何的改變。在更複雜的環境下,同樣的問題可能會令系統崩潰掉。對於一個處理過運用XML的大型系統的人來說,他就會遇到過這個問題。要編寫一個載入的過程通常是非常單調乏味的,由於資料來源或者目標Java類的改變,你需要經常更新和重新編寫代碼。在這裡我要介紹另一個解決方案,那就是使用映射,它通常使用更少的編碼,並且可以在目標Java類發生改變後更新自己。
最初,我想介紹一個使用Reflection在運行期間配置資料的方案。在開始的時候,一個動態、基於映射的程式要比一個簡單的方法更有吸引力多了。隨後,我要揭示出運行時Reflection的複雜性和冒險性。這篇文章將介紹由運行時的Reflection到活動的代碼產生。
由簡單到複雜
我的第一個方案使用一個載入類將資料從一個檔案載入到對象中。我的原始碼含有對StringTokenizer對象下一節點方法的多次調用。在修改多次後,我的編碼邏輯變得非常的直接、系統化。該類構造了專用的代碼。在這個初始方案中,我只需要使用3個基本的對象:
1、Strings
2、Objects
3、Arrays of objects
你可以影射類的對象來產生代碼塊,如下表所示:
被影射來產生代碼塊的對象
| Field type |
Code block |
| String |
fileIterator.nextString(); |
| Object[] |
Vector collector = new Vector(); while(fileIterator.hasMoreDataForArray()){ Object data = initializeObject(fileIterator)collector.add(data); } Object[] objArray = new Object[collector.size()]; collector.copyInto(objArray); |
| Object |
initializeObject(fileIterator); |
**************表一**************
我已經使用這個方案作了幾次編碼,因此我在寫代碼之前我已經知道該方案和代碼的結構。痛點在於該類是變化的。類的名字、成份和結構在任何時候都可能發生變化,而任何的改變你都要重新編寫代碼。雖然會發生這些變化,但是結構和下載的流程仍然是一樣的;在寫代碼前,我仍然知道代碼的結構和成份。我需要一個方法,來將頭腦中的編碼流程轉換為一個可重用的、自動的形式。由於我是一個有效率的編程者,我很快就厭倦了編寫幾乎一樣的代碼,這時我想到了映射。
資料配置通常需要一個源到目的資料的影射。影射可以是一個圖解、DTD(document type definition,文件類型定義),檔案格式等。在這個例子中,映射將一個對象的類定義解釋為我們要映射的流程。映射可以在運行時複製代碼的功能。在需要重寫代碼時,我將載入的過程用映射來代替,它所需要的時間和重寫是一樣的。