程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> 動態擴展Java應用

動態擴展Java應用

編輯:JAVA編程入門知識

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 

  摘要:你想寫出無需改變源代碼就可以進行擴展的程序嗎?這篇文章介紹了如何使用interface和動態class載入來創建高擴展性的系統。從中你也可以學習到如何令其他的編程者和用戶不需你的源代碼,就可以對程序進行擴展。首先我們看一個沒有使用interface和動態載入的簡單例子,然後再講述一個動態載入類的例子,這些類是由一個文件或者數據庫的表格中讀取的。
  
  你曾經開發過一個要經常添加新功能的應用嗎?在下面的例子中,市場部將會為每個顧客提供各種各樣的價格處理。你的程序需要處理這些新的需求,你也必須讓用戶可以定制你的軟件而無需改變源代碼。
  
  你可以做到避免修改現有的代碼並且測試加入的新功能嗎?你可以做到無需重新編譯全部的東西來加入新的類嗎?答案是可以的,你可能已經猜到了,就是使用interface和動態類載入。
  
  要說明一下的是,為了說明方便,這裡介紹的類和體系都是經過簡化的。
  
  什麼是interface(接口)?
  
  interface只是描述一個對象是如何被調用的。當你定義了一個接口,你就定義了其它的對象如何使用它。
  
  對於大部分使用Java的人來說,你們可能已經知道接口是什麼東西。但對於那些仍然不清楚的人,我將介紹一些基本的知識,然後創建一些復雜的例子。假如你已經很清楚接口的知識,你可以直接跳到“使用字符串來指定類名字”的部分。
  
  接口的威力
  
  以下的例子說明了接口的威力。假定你的客戶是搞經紀的,他們想讓你建立一個交易的系統。他們的交易是各種各樣的:包括有股票、債券和日用品等等。不同客戶的交易數量也是不一樣的,該數量由客戶稱為pricing plans的東東來定義。
  
  你首先考慮類的設計。主要的類和它們的屬性由客戶來定義,可以是:
  
  Customer(顧客):Name(名字),Address(地址),Phone(電話)和PricingPlan
  
  Trade(交易):TradeType(股票、債券或者日用品),ItemTraded(股票的記號)、NumberOfItemsTraded, ItemPrice, CommissionAmount
  
  PricingPlan:通過一個過程的調用來計算該交易的CommissionAmount
  
  不使用interface的編碼
  
  開始編碼時你可以不使用接口,然後再由該代碼增強其功能。現在,該客戶有兩個標價計劃定義如下:
  
  計劃1:對於常規的顧客,$20/交易
  
  計劃2:一個月中的前10個交易,$15/交易,以後的 $10/交易
  
  Trade對象使用一個PricingPlan對象來計算要收顧客多少傭金。你為每個標價計劃都創建了一個PricingPlan類。對於計劃1,該類稱為PricingPlan20,而計劃2的類則稱為PricingPlan1510。兩個類都通過一個稱為CalcCommission()的過程來計算傭金。代碼如下所示:
  
  類名: PricingPlan20
  
  public double calculateCommission( Trade trade )
  {
   return 20.0;
  }
  
  
  類名: PricingPlan1510
  
  public double calculateCommission( Trade trade )
  {
   double commission = 0.0;
  
   if( trade.getCustomer().getNumberOfTradesThisMonth() <= 10 )
   commission = 15.0;
   else
   commission = 10.0;
  
   return commission;
  }
  
  以下是在交易中得到傭金的代碼:
  
  public double getCommissionPrice()
  {
   double commissionPrice = 0.0;
  
   if( getCustomer().getPlanId() == 1 )
   {
  PricingPlan20 plan1 = new PricingPlan20();
  commissionPrice = plan1.calculateCommission( this.getCustomer() );
  plan1 = null;
   }
   else
   {
  PricingPlan1510 plan2 = new PricingPlan1510();
  commissionPrice = plan2.calculateCommission( this.getCustomer() );
  plan2 = null;
   }
  
   return commissionPrice;
  }
  
  使用interface
  
  使用接口的話,將會令上面的例子變得更加簡單。你可以創建PricingPlan的接口,然後定義實現該接口的PricngPlan類:
  
  接口名:IPricingPlan
  
  public interface IPricingPlan {
   public double calculateCommission( Trade trade );
  }
  
  由於你定義的是一個接口,所以你無需為calculateCommission()定義一個方法體。真正的PricingPlan類將會實現該部分的代碼。接著你就要修改PricingPlan類,第一步是聲明它將會實現你剛剛定義的接口。你只要在PricingPlan類的定義中加入以下代碼就可以:
  
  public class PricingPlan20 extends Object implements IPricingPlan {
  
  在Java中,當你聲明將實現一個接口的時候,你必須實現該接口中的全部方法(除非你要創建一個抽象類,這裡不討論)。因此所有實現IPricingPlan的類都必須定義一個calculateCommission()的方法。該方法的所有標記必須和接口定義的完全一樣,所以它必須接受一個Trade對象,由於我們的兩個PricingPlan類中都已經定義了calculateCommission()方法,因為我們沒有必要作進一步的修改。假如你要創建新的PricingPlan類,你就必須實現IPricingPlan和相應的calculateCommission()方法。
  
  接著你可以修改Trade類的getCommissionPrice()方法來使用該接口:
  
  類名: Trade
  
  public double getCommissionPrice()
  {
   double commissionPrice = 0.0;
  
   IPricingPlan plan;
  
   if( getCustomer().getPlanId() == 1 )
   {
  plan = new PricingPlan20();
   }
   else
   {
  plan = new PricingPlan1510();
   }
  
   commissionPrice = plan.calculateCommission( this );
   return commissionPrice;
  }
  
  要注重的是,你將PricingPlan變量定義為IPricingPlan接口。你實際創建的對象根據客戶的標價計劃而定。由於兩個PricingPlan類都實現了IPricingPlan接口,所以你可以將兩個新的實例賦給同一個變量。Java實際上並不關心實現該接口的實際對象,它只是關心接口。
  
  使用字符串來指定類名
  
  假定老板告訴你該公司又有兩個新的價格計劃,接著還有更多。這些價格計劃是每交易$8或者$10。你決定要創建兩個新的PricingPlan類: PricingPlan8 和 PricingPlan10。
  
  在這種情況下,你必須修改Trade類來包含這些新的價格計劃。你可以加入更多的if/then/else句子,但這不是一個好方法,假如價格計劃變得越來越多時,代碼將會顯得十分粗笨。另一個選擇是通過Class.forName() 方法來創建PricingPlan實例,而不是通過new。Class.forName()方法可讓你通過一個字符串名字來創建實例,以下就是在Trade類中應用該方法的例子:
  
  類名: Trade
  
  public double getCommissionPrice()
  {
   double commissionPrice = 0.0;
  
   IPricingPlan plan;
   Class commissionClass;
  
   try
   {
  if( getCustomer().getPlanId() == 1 )
  {
   commissionClass = Class.forName( "string_interfaces.PricingPlan20" );
  }
  else
  {
   commissionClass = Class.forName( "string_interfaces.PricingPlan1510" );


 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved