JAVA基礎:Java程序的臟數據問題

發表于:2007-05-25來源:作者:點擊數: 標簽:java問題程序基礎數據
臟數據(Out-of-date data),指過時的數據。 如果在您的 Java 程序中存在臟數據,將或多或少地給軟件系統帶來一些問題,如:無法實時地應用已經發生改變的配置,軟件系統出現一些莫名其妙的、難以重現的、后果嚴重的錯誤等等。盡量避免臟數據的存在是非常有價

臟數據(Out-of-date data),指過時的數據。

  如果在您的Java程序中存在臟數據,將或多或少地給軟件系統帶來一些問題,如:無法實時地應用已經發生改變的配置,軟件系統出現一些莫名其妙的、難以重現的、后果嚴重的錯誤等等。盡量避免臟數據的存在是非常有價值的。本文希望能在這方面給同行們一點幫助。

Fragment 1. 緩存技術的臟數據問題

  /**
    * A report printer is used to print a report.
    *
    * @version 1.0 9/9/2003
    * @author Bill
    */
   public class ReportPrinter {
   /**
       * Constructs a ReportPrinter instance.
   */
      public ReportPrinter() {
         // do something...
   }

   /**
       * Prints a printable.
  *
       * @param printable the specified printable object
   */
      public void print(Printable printable) {
         Graphics g = getGraphics();
         g.setFont(getReportFont(printable.getFont());

         printable.print(g);
   }

   /**
       * Returns the corresponding report font of a java font.
  *
       * @param javaFont the specified java font
       * @return the corresponding report font
   */
     private Font getReportFont(font javaFont) {
         Font reportFont = fontMap.get(javaFont);

         if(reportFont == null) {
           reportFont = loadFont(javaFont);
           fontMap.put(javaFont, reportFont);
      }

         return reportFont;
   }

   /**
      * Loads the corresponding report font of a java font.
  *
       * @param javaFont the specified java font
       * @param the corresponding report font
   */
      protected static Font loadFont(Font javaFont) {
         Font reportFont = null;

         // do something...

         return reportFont;
   }

   /**
       * The font map(java font->report font).
   */
     private static HashMap fontMap = new HashMap();
  }

  Fragment 1中,由于裝載一個java font所對應的report font開銷較大,使用了緩存技術來避免這種開銷。這是一種常見的提高性能的方式,而且在一般情況下運行良好。但是Fragment 1的設計與實現可能是不完備的,因為極有可能一個java font所對應的report font在系統啟動之后發生變化,在這種變化發生之后,只有重啟軟件系統才能裝載之,這常常是最終用戶的抱怨之一。更可怕的是,類似的這種臟數據的存在還可能帶來其它嚴重的、無法想象的后果。

  如何避免使用緩存技術所帶來的臟數據問題呢?

  在設計、實現和測試時,應該清晰定義緩存數據的更新:
  i. 不考慮緩存數據的更新,重啟軟件系統是一種必要的方式;
  ii. 不考慮緩存數據的更新,緩存數據不可能成為臟數據(但在軟件系統中,往往“不可能”會在一次又一次的重構之后變為“可能”);
  iii. 考慮緩存數據的更新,當源數據變化時,實時更新緩存數據。

Fragment 2. Singleton模式的臟數據問題

  /**
    * A storage usage handler is used to query the storage usage of users.
    *
    * @version 1.0 9/9/2003
    * @author Bill
    */
   public class StorageUsageHandler {
   /**
       * Returns a StorageUsageHandler instance.
  *
       * @return the single StorageUsageHandler instance
   */
      public static StorageUsageHandler getStorageUsageHandler() {
         if(handler == null) {
          handler = new StorageUsageHandler();
      }

         return handler;
   }

   /**
       * Constructs a StorageUsageHandler instance.
   */
     private StorageUsageHandler() {
        users = Context.getAllUsers();
   }

   /**
       * Returns the storage sizes of all the users.
  *
       * @return the storage sizes
   */
      public long[] getSizes() {
         long sizes[] = new long[users.size()];

        for(int i = 0; i < users.size(); i++) {
           sizes[i] = getOneSize(users.get(i));
    }
   }

   /**
       * Returns the storage size of a user.
  *
       * @param user the specified user
       * @return the storage size
   */
      protected long getSize(User user) {
         // do something...

       return 0;
   }

   /**
       * The StorageUsageHandler singleton.
   */
     private static StorageUsageHandler handler;

   /**
       * The users.
   */
     private List users;
  }

  您看出了問題所在嗎?

  Fragment 2中,由于沒有必要次次實例化StorageUsageHandler而帶來不必要的開銷,采用了Singleton模式以保證StorageUsageHandler只被實例化一次。

  在實例化SotrageUsageHandler時,StorageUsageHandler的類成員users將被賦值。由于不存在任何對users重新賦值的方法,一直駐留在軟件系統中的users將不會發生任何變化。在軟件系統啟動之后,增加、刪除或修改用戶的操作經常會發生,而一旦發生這類操作,users就成為了臟數據,Fragment 2將無法正常工作。

  如何避免使用Singleton模式所帶來的臟數據問題呢?

  對于Singleton類的類成員:
  i. 對于與Singleton類外部無依賴關系的類成員,不存在這種問題;
  ii. 對于依賴于Singleton類外部的類成員,且該類成員不存在更新機制,最好是將其去掉,需要時從Singleton類外部直接獲??;如果這種辦法不可行,應提供機制以確保在使用該類成員之前,該類成員已經被更新過。

Fragment 3. 類使用的臟數據問題

  /**
    * A storage usage handler is used to query the storage usage of users.
    *
    * @version 1.0 9/9/2003
    * @author Bill
    */
   public class StorageUsageHandler implements AdminHandler {
   /**
       * Constructs a StorageUsageHandler instance.
   */
     private StorageUsageHandler() {
        users = Context.getAllUsers();
   }

   /**
       * Returns the storage sizes of all users.
  *
       * @return the storage sizes
   */
      public long[] getSizes() {
         long sizes[] = new long[users.size()];

        for(int i = 0; i < users.size(); i++) {
           sizes[i] = getOneSize(users.get(i));
    }
   }

   /**
       * Returns the storage size of a user.
  *
       * @param user the specified user
       * @return the storage size
   */
      protected long getSize(User user) {
         // do something...

       return 0;
   }

   /**
       * Displays the storage usage of users.
  *
       * @param req the http servlet request
       * @param res the http servlet response
  *
       * @throws IOException
       * @throws ServletException
   */
      public void process(HttpServletRequest req, HttpServletResponse res)
         throws IOException, ServletException {

         res.setContentType("text/html");
         res.setHeader("Cache-Control", "no-cache");
         res.setHeader("Pragma","no-cache");
         res.setDateHeader("Expires", 0);

         PrintWriter writer = new PrintWriter(res.getOutputStream());
         long sizes[] = getsizes();
         writer.println("");
         writer.println("

原文轉自:http://www.anti-gravitydesign.com

評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97