彩虹天堂
          技術源于生活
          posts - 0,  comments - 2,  trackbacks - 0
          Classloaders

          在許多情況下,使用多個類載入器是很普通的--包括servlet容器--所以不管你在實現你的單例類時是多么小心你都最終可以得到多個單例類的實例。如果你想要確保你的單例類只被同一個的類載入器裝入,那你就必須自己指定這個類載入器;例如:

          Java代碼 復制代碼
          1. private static Class getClass(String classname)     
          2.                                          throws ClassNotFoundException {    
          3.       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();    
          4.      
          5.       if(classLoader == null)    
          6.          classLoader = Singleton.class.getClassLoader();    
          7.      
          8.       return (classLoader.loadClass(classname));    
          9.    }    
          10. }   


          這個方法會嘗試把當前的線程與那個類載入器相關聯;如果classloader為null,這個方法會使用與裝入單例類基類的那個類載入器。這個方法可以用Class.forName()代替。

          序列化

          如果你序列化一個單例類,然后兩次重構它,那么你就會得到那個單例類的兩個實例,除非你實現readResolve()方法,像下面這樣:
          例12 一個可序列化的單例類

          Java代碼 復制代碼
          1. import org.apache.log4j.Logger;    
          2.      
          3. public class Singleton implements java.io.Serializable {    
          4.    public static Singleton INSTANCE = new Singleton();    
          5.      
          6.    protected Singleton() {    
          7.       // Exists only to thwart instantiation.    
          8.    }    
          9.    private Object readResolve() {    
          10.             return INSTANCE;    
          11.       }   
          12.    }   


          上面的單例類實現從readResolve()方法中返回一個唯一的實例;這樣無論Singleton類何時被重構,它都只會返回那個相同的單例類實例。
          例13測試了例12的單例類:
          例13 測試一個可序列化的單例類

          Java代碼 復制代碼
          1. import java.io.*;    
          2. import org.apache.log4j.Logger;    
          3. import junit.framework.Assert;    
          4. import junit.framework.TestCase;    
          5.      
          6. public class SingletonTest extends TestCase {    
          7.    private Singleton sone = null, stwo = null;    
          8.    private static Logger logger = Logger.getRootLogger();    
          9.      
          10.    public SingletonTest(String name) {    
          11.       super(name);    
          12.    }    
          13.    public void setUp() {    
          14.       sone = Singleton.INSTANCE;    
          15.       stwo = Singleton.INSTANCE;    
          16.    }    
          17.    public void testSerialize() {    
          18.       logger.info("testing singleton serialization...");    
          19. <STRONG>      writeSingleton();    
          20.       Singleton s1 = readSingleton();    
          21.       Singleton s2 = readSingleton();    
          22.       Assert.assertEquals(true, s1 == s2);</STRONG>   }    
          23.    private void writeSingleton() {    
          24.       try {    
          25.          FileOutputStream fos = new FileOutputStream("serializedSingleton");    
          26.          ObjectOutputStream oos = new ObjectOutputStream(fos);    
          27.          Singleton s = Singleton.INSTANCE;    
          28.      
          29.          oos.writeObject(Singleton.INSTANCE);    
          30.          oos.flush();    
          31.       }    
          32.       catch(NotSerializableException se) {    
          33.          logger.fatal("Not Serializable Exception: " + se.getMessage());    
          34.       }    
          35.       catch(IOException iox) {    
          36.          logger.fatal("IO Exception: " + iox.getMessage());    
          37.       }    
          38.    }    
          39.    private Singleton readSingleton() {    
          40.       Singleton s = null;    
          41.      
          42.       try {    
          43.          FileInputStream fis = new FileInputStream("serializedSingleton");    
          44.          ObjectInputStream ois = new ObjectInputStream(fis);    
          45.          s = (Singleton)ois.readObject();    
          46.       }    
          47.       catch(ClassNotFoundException cnf) {    
          48.          logger.fatal("Class Not Found Exception: " + cnf.getMessage());    
          49.       }    
          50.       catch(NotSerializableException se) {    
          51.          logger.fatal("Not Serializable Exception: " + se.getMessage());    
          52.       }    
          53.       catch(IOException iox) {    
          54.          logger.fatal("IO Exception: " + iox.getMessage());    
          55.       }    
          56.       return s;    
          57.    }    
          58.    public void testUnique() {    
          59.       logger.info("testing singleton uniqueness...");    
          60.       Singleton another = new Singleton();    
          61.      
          62.       logger.info("checking singletons for equality");    
          63.       Assert.assertEquals(true, sone == stwo);    
          64.    }    
          65. }   


          前面這個測試案例序列化例12中的單例類,并且兩次重構它。然后這個測試案例檢查看是否被重構的單例類實例是同一個對象。下面是測試案例的輸出:

          Java代碼 復制代碼
          1. Buildfile: build.xml    
          2.      
          3. init:    
          4.      [echo] Build 20030422 (22-04-2003 11:32)    
          5.      
          6. compile:    
          7.      
          8. run-test-text:    
          9.      [java] .INFO main: testing singleton serialization...    
          10.      [java] .INFO main: testing singleton uniqueness...    
          11.      [java] INFO main: checking singletons for equality    
          12.      
          13.      [java] Time: 0.1    
          14.      
          15.      [java] OK (2 tests)   


          單例模式結束語

          單例模式簡單卻容易讓人迷惑,特別是對于Java的開發者來說。在這篇文章中,作者演示了Java開發者在顧及多線程、類載入器和序列化情況如何實現單例模式。作者也展示了你怎樣才能實現一個單例類的注冊表,以便能夠在運行期指定單例類。
          posted on 2008-05-05 22:12 bcterry 閱讀(79) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          留言簿

          文章檔案

          搜索

          •  

          最新評論

          主站蜘蛛池模板: 五指山市| 定结县| 眉山市| 饶阳县| 亳州市| 新巴尔虎右旗| 林口县| 闻喜县| 绥芬河市| 西城区| 贡嘎县| 伊通| 潞城市| 荥阳市| 鹿邑县| 濮阳县| 蕲春县| 木兰县| 肥城市| 嘉鱼县| 阿拉善右旗| 阜宁县| 临洮县| 都匀市| 铜陵市| 永嘉县| 甘泉县| 丰城市| 固镇县| 黄大仙区| 独山县| 万全县| 晋江市| 泾阳县| 平遥县| 慈溪市| 蓬溪县| 黄龙县| 阜新市| 营口市| 榆社县|