熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

爪哇語言單態創立性模式介紹(下)

2022-06-13   來源: Java高級技術 

  登記式單態類
  登記式單態類是GoF為了克服餓漢式單態類及懶漢式式單態類均不可繼承的缺點而設計的 作者把他們的例子翻譯為爪哇語言並將它自己實例化的方式從懶漢式改為餓漢式只是它的 子類實例化的方式只能是懶漢式的這是無法改變的
   
  圖 登記式單態類的一個例子 
  圖中的關系線表明此類自已將自己實例化
  package comjavapatternssingletondemos;
  import javautilHashMap;
  public class RegSingleton {
   protected RegSingleton() {}
   static public RegSingleton getInstance(String name)
   {
  if (name == null)
  {
   name = comjavapatternssingletondemosRegSingleton;
  }
  if (m_registryget(name) == null)
  {
   try
   {
  m_registryput( name ClassforName(name)newInstance() ) ;
   }
   catch(Exception e)
   {
    Systemoutprintln(Error happened);
   }
  }
  return (RegSingleton) (m_registryget(name) );
   }
   static private HashMap m_registry = new HashMap();
   static
   {
  RegSingleton x = new RegSingleton();
  m_registryput( xgetClass()getName() x);
   }
   public String about()
   {
  return Hello I am RegSingleton;
   }
  }
  代碼清單 登記式單態類(注意為簡單起見這裡沒有考慮多線程訪問限制的問題讀者可自行加入一個有雙重 檢查的訪問限制)
  它的子類
   
  圖 登記式單態類子類的一個例子
  圖中的關系線表明此類是由父類將自己實例化的 
  package comjavapatternssingletondemos;
  import javautilHashMap;
  public class RegSingletonChild extends RegSingleton
  {
   public RegSingletonChild() {}
   static public RegSingletonChild getInstance()
   {
  return (RegSingletonChild) RegSingletongetInstance(
  comjavapatternssingletondemosRegSingletonChild );
   }
   public String about()
   {
  return Hello I am RegSingletonChild;
   }
  }
  代碼清單 登記式單態類的子類
  在GoF原始的例子中並沒有getInstance()方法這樣得到子類必須調用文類的getInstance(String name) 方法並傳入子類的名字很不方便 作者在登記式單態類子類的例子裡加入了getInstance()方法這樣做的好處是RegSingletonChild 可以通過這個方法返還自已的實例而這樣做的缺點是由於數據類型不同無法在RegSingleton提供 這樣一個方法
  由於子類必須充許父類以構造子調用產生實例因此它的構造子必須是公開的這樣一來就等於允許了 以這樣方式產生實例而不在父類的登記中這是登記式單態類的一個缺點
  GoF曾指出由於父類的實例必須存在才可能有子類的實例這在有些情況下是一個浪費 這是登記式單態類的另一個缺點
  爪哇語言裡的垃圾回收
  爪哇語言裡垃圾回收使得單態類的使用變得有點復雜原因就在於JDK版裡加進去的類的自動清除 這種類的垃圾回收會清除掉類本身而不僅僅是對象!事實上JDK甚至可以清除掉一些系統類!
  在JDKx版本裡類的自動清除尚未加入
  在JDK及以後的版本裡升陽公司又收緊了類的垃圾回收規則它規定所有通過局部的和系統的 類加載器加載的類永不被回收並且通過其它類加載器加載的類只有在加載器自己被回收後才可被回收
  在版JDK裡使用單態類的讀者如果不了解這一版爪哇語言的特點很有可能會遇到類消失掉的奇特問題 為了使你的單態類能在所有版本的爪哇環境裡使用作者特別提供一個看守類程序它能保證你的單態類 甚至其它任何對象一旦交給看守對象即不會莫名其妙地被垃圾回收器回收直到你把它從看守 那裡把它釋放出來
   
  圖 看守類的一個例子 
  package comjavapatternssingletondemos;
  import javautilVector;
  /**
  * This class keeps your objects from garbage collected
  */
  public class ObjectKeeper extends Thread {
   private ObjectKeeper()
   {
  new Thread(this)start();
   }
   public void run()
   {
  try { join(); }
  catch (InterruptedException e) {}
   }
   /**
   * Any object passed here will be kept until you call discardObject()
   */
   public static void keepObject(Object myObject)
   {
  Systemoutprintln( Total number of kept objects: +     m_keptObjectssize());
  m_keptObjectsadd(myObject);
  Systemoutprintln( Total number of kept objects: +           m_keptObjectssize());
   }
   /**
   * This method will remove the protect of the object you pass in and make it
   * available for Garbage Collector to collect
   */
   public static void discardObject(Object myObject)
   {
  Systemoutprintln( Total number of kept objects: +           m_keptObjectssize());
  m_keptObjectsremove(myObject);
  Systemoutprintln( Total number of kept objects: +           m_keptObjectssize());
   }
   private static ObjectKeeper m_keeper = new ObjectKeeper();
   private static Vector m_keptObjects = new Vector();
  } 
  代碼清單 看守類的一個實現
  看守類應當自我實例化而且在每個系統裡只需一個實例這就意味著看守類本身就應當是單態類當然類 消失的事情絕不可以發生在它自己身上作者提供的例子剛好滿足所有的要求
  一個實用的例子
  這裡作者給出一個讀取屬性(properties)文件的單態類作為單態類的一個實用的例子 屬性文件如同老式的視窗編程時的ini文件屬於系統的資源而讀取屬性文件即為資源管理 顯然應當由一個單態類負責
   
  圖 這個例子的UML 
  顯然在大多數的系統中都會涉及屬性文件的讀取問題因而這個例子非常有實用價值 在這個例子裡作者假定需要讀取的屬性文件就在當前目錄中且名為singletonproperties 在這個文件中有如下的一些屬性項
  em=How
  em=are
  em=you
  em=doing
  em=?
  代碼清單 屬性文件內容
  本例子的源代碼如下
  package comjavapatternssingletondemos;
  import javautilProperties;
  import javaioFileInputStream;
  import javaioFile;
  public class ConfigManager
  {
   /**
   * 私有的構造子 用以保證實例化的唯一性
   */
   private ConfigManager()
   {
  m_file = new File(PFILE);
  m_lastModifiedTime = m_filelastModified();
  if(m_lastModifiedTime == )
  {
   Systemerrprintln(PFILE + file does not exist!);
  }
  m_props = new Properties();
  try
  {
   m_propsload(new FileInputStream(PFILE));
  }
  catch(Exception e)
  {
   eprintStackTrace();
  }
   }
   /**
   *
   * @return 返還ConfigManager類的單一實例
   */
   synchronized public static ConfigManager getInstance()
   {
  return m_instance;
   }
   /**
   * 讀取一特定的屬性項
   *
   * @param name 屬性項的項名
   * @param defaultVal 屬性項的缺省值
   * @return 屬性項的值(如此項存在) 缺省值(如此項不存在)
   */
   final public Object getConfigItem(String name Object defaultVal)
   {
  long newTime = m_filelastModified();
  // 檢查屬性文件是否被其它程序(多數情況是程序員手動)修改過
  // 如果是重新讀取此文件
  if(newTime == )
  {
   // 屬性文件不存在
   if(m_lastModifiedTime == )
   {
    Systemerrprintln(PFILE + file does not exist!);
   }
   else
   {
    Systemerrprintln(PFILE + file was deleted!!);
   }
   return defaultVal;
  }
  else if(newTime > m_lastModifiedTime)
  {
   m_propsclear
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27517.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.