深入單例模式 java,深入單例模式四

Java代碼 icon_copy.gif

privatestaticClass?getClass(String?classname)

throwsClassNotFoundException?{

ClassLoader?classLoader?=?Thread.currentThread().getContextClassLoader();

if(classLoader?==null)

classLoader?=?Singleton.class.getClassLoader();

return(classLoader.loadClass(classname));

}

}

private static Class getClass(String classname)

throws ClassNotFoundException {

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

if(classLoader == null)

classLoader = Singleton.class.getClassLoader();

return (classLoader.loadClass(classname));

}

}

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

序列化

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

例12 一個可序列化的單例類

Java代碼 icon_copy.gif

importorg.apache.log4j.Logger;

publicclassSingletonimplementsjava.io.Serializable?{

publicstaticSingleton?INSTANCE?=newSingleton();

protectedSingleton()?{

//?Exists?only?to?thwart?instantiation.

}

privateObject?readResolve()?{

returnINSTANCE;

}

}

import org.apache.log4j.Logger;

public class Singleton implements java.io.Serializable {

public static Singleton INSTANCE = new Singleton();

protected Singleton() {

// Exists only to thwart instantiation.

}

private Object readResolve() {

return INSTANCE;

}

}

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

例13測試了例12的單例類:

例13 測試一個可序列化的單例類

Java代碼 icon_copy.gif

importjava.io.*;

importorg.apache.log4j.Logger;

importjunit.framework.Assert;

importjunit.framework.TestCase;

publicclassSingletonTestextendsTestCase?{

privateSingleton?sone?=null,?stwo?=null;

privatestaticLogger?logger?=?Logger.getRootLogger();

publicSingletonTest(String?name)?{

super(name);

}

publicvoidsetUp()?{

sone?=?Singleton.INSTANCE;

stwo?=?Singleton.INSTANCE;

}

publicvoidtestSerialize()?{

logger.info("testing?singleton?serialization...");

??????writeSingleton();

Singleton?s1?=?readSingleton();

Singleton?s2?=?readSingleton();

Assert.assertEquals(true,?s1?==?s2);???}

privatevoidwriteSingleton()?{

try{

FileOutputStream?fos?=newFileOutputStream("serializedSingleton");

ObjectOutputStream?oos?=newObjectOutputStream(fos);

Singleton?s?=?Singleton.INSTANCE;

oos.writeObject(Singleton.INSTANCE);

oos.flush();

}

catch(NotSerializableException?se)?{

logger.fatal("Not?Serializable?Exception:?"+?se.getMessage());

}

catch(IOException?iox)?{

logger.fatal("IO?Exception:?"+?iox.getMessage());

}

}

privateSingleton?readSingleton()?{

Singleton?s?=null;

try{

FileInputStream?fis?=newFileInputStream("serializedSingleton");

ObjectInputStream?ois?=newObjectInputStream(fis);

s?=?(Singleton)ois.readObject();

}

catch(ClassNotFoundException?cnf)?{

logger.fatal("Class?Not?Found?Exception:?"+?cnf.getMessage());

}

catch(NotSerializableException?se)?{

logger.fatal("Not?Serializable?Exception:?"+?se.getMessage());

}

catch(IOException?iox)?{

logger.fatal("IO?Exception:?"+?iox.getMessage());

}

returns;

}

publicvoidtestUnique()?{

logger.info("testing?singleton?uniqueness...");

Singleton?another?=newSingleton();

logger.info("checking?singletons?for?equality");

Assert.assertEquals(true,?sone?==?stwo);

}

}

import java.io.*;

import org.apache.log4j.Logger;

import junit.framework.Assert;

import junit.framework.TestCase;

public class SingletonTest extends TestCase {

private Singleton sone = null, stwo = null;

private static Logger logger = Logger.getRootLogger();

public SingletonTest(String name) {

super(name);

}

public void setUp() {

sone = Singleton.INSTANCE;

stwo = Singleton.INSTANCE;

}

public void testSerialize() {

logger.info("testing singleton serialization...");

writeSingleton();

Singleton s1 = readSingleton();

Singleton s2 = readSingleton();

Assert.assertEquals(true, s1 == s2); }

private void writeSingleton() {

try {

FileOutputStream fos = new FileOutputStream("serializedSingleton");

ObjectOutputStream oos = new ObjectOutputStream(fos);

Singleton s = Singleton.INSTANCE;

oos.writeObject(Singleton.INSTANCE);

oos.flush();

}

catch(NotSerializableException se) {

logger.fatal("Not Serializable Exception: " + se.getMessage());

}

catch(IOException iox) {

logger.fatal("IO Exception: " + iox.getMessage());

}

}

private Singleton readSingleton() {

Singleton s = null;

try {

FileInputStream fis = new FileInputStream("serializedSingleton");

ObjectInputStream ois = new ObjectInputStream(fis);

s = (Singleton)ois.readObject();

}

catch(ClassNotFoundException cnf) {

logger.fatal("Class Not Found Exception: " + cnf.getMessage());

}

catch(NotSerializableException se) {

logger.fatal("Not Serializable Exception: " + se.getMessage());

}

catch(IOException iox) {

logger.fatal("IO Exception: " + iox.getMessage());

}

return s;

}

public void testUnique() {

logger.info("testing singleton uniqueness...");

Singleton another = new Singleton();

logger.info("checking singletons for equality");

Assert.assertEquals(true, sone == stwo);

}

}

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

Java代碼 icon_copy.gif

Buildfile:?build.xml

init:

[echo]?Build20030422(22-04-200311:32)

compile:

run-test-text:

[java]?.INFO?main:?testing?singleton?serialization...

[java]?.INFO?main:?testing?singleton?uniqueness...

[java]?INFO?main:?checking?singletonsforequality

[java]?Time:0.1

[java]?OK?(2tests)

Buildfile: build.xml

init:

[echo] Build 20030422 (22-04-2003 11:32)

compile:

run-test-text:

[java] .INFO main: testing singleton serialization...

[java] .INFO main: testing singleton uniqueness...

[java] INFO main: checking singletons for equality

[java] Time: 0.1

[java] OK (2 tests)

單例模式結束語

單例模式簡單卻容易讓人迷惑,特別是對于Java的開發者來說。在這篇文章中,作者演示了Java開發者在顧及多線程、類載入器和序列化情況如何實現單例模式。作者也展示了你怎樣才能實現一個單例類的注冊表,以便能夠在運行期指定單例類。

posted on 2008-05-05 22:12 bcterry 閱讀(38) 評論(0) ?編輯 ?收藏

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392253.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392253.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392253.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux下配置SS5(SOCK5)代理服務

SOCK5代理服務器 官網: http://ss5.sourceforge.net/ yum -y install gcc gcc-c automake make pam-devel openldap-devel cyrus-sasl-devel 一、安裝 # tar xvf ss5-3.8.9-5.tar.gz # cd ss5-3.8.9-5 # ./configure && make && make install 二、修改配置文…

劉備和諸葛亮鬧翻:無意說出蜀國滅亡的根源?

導讀:身為管理者,一件事情,自己做是滿分,別人做是八十分,寧可讓人去做八十分,自己也得跳出來看全局。緊抓大權不放,要么自己干到死,要么是敗于戰略!! 諸葛亮去…

mysql 時間推移_隨著時間的推移可視化COVID-19新案例

mysql 時間推移This heat map shows the progression of the COVID-19 pandemic in the United States over time. The map is read from left to right, and color coded to show the relative numbers of new cases by state, adjusted for population.該熱圖顯示了美國COVID…

leetcode 959. 由斜杠劃分區域(并查集)

在由 1 x 1 方格組成的 N x N 網格 grid 中,每個 1 x 1 方塊由 /、\ 或空格構成。這些字符會將方塊劃分為一些共邊的區域。 (請注意,反斜杠字符是轉義的,因此 \ 用 “\” 表示。)。 返回區域的數目。 示例 1&#x…

rcu寬限期_如何處理寬限期錯誤:靜默失敗不是一種選擇

rcu寬限期by Rina Artstain通過麗娜阿斯特斯坦 I’ve never really had much of an opinion about error handling. This may come as a shock to people who know me as quite opinionated (in a good way!), but yeah. If I was coming into an existing code base I just d…

描述符、迭代器、生成器

描述符:將某種特殊類型的類的實例指派給另一個類的屬性。 此處特殊類型的要求,至少實現”__set__(self , instance , owner)“、”__get__(self , instance , value)“、”__delete__(self , instance )“三個方法中的一個。 >>> class MyDecri…

php模擬表單提交登錄,PHP模擬表單的post請求實現登錄

stuid > $stuid,pwd > $pwd);$ch curl_init (); //初始化curlcurl_setopt ( $ch, CURLOPT_URL, $uri );curl_setopt ( $ch, CURLOPT_POST, 1 ); //使用post請求curl_setopt ( $ch, CURLOPT_HEADER, 0 );curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );curl_setopt ( $…

去除list集合中重復項的幾種方法

因為用到list&#xff0c;要去除重復數據&#xff0c;嘗試了幾種方法。記錄于此。。。 測試數據&#xff1a; List<string> li1 new List<string> { "8", "8", "9", "9" ,"0","9"};List<string&g…

Crystal Reports第一張報表

新建一個網站項目&#xff0c;1. 設置數據庫 從服務器資源管理器中&#xff0c;數據連接中添加新連接&#xff0c;用Microsoft Access數據庫文件作為數據提供程序&#xff0c;連接上Crystal Reports的用例的數據庫Xtreme2. 創建新Crystal Reports報表 在工程項目中添加一個…

leetcode 1128. 等價多米諾骨牌對的數量

給你一個由一些多米諾骨牌組成的列表 dominoes。 如果其中某一張多米諾骨牌可以通過旋轉 0 度或 180 度得到另一張多米諾骨牌&#xff0c;我們就認為這兩張牌是等價的。 形式上&#xff0c;dominoes[i] [a, b] 和 dominoes[j] [c, d] 等價的前提是 ac 且 bd&#xff0c;或是…

海量數據尋找最頻繁的數據_尋找數據科學家的“原因”

海量數據尋找最頻繁的數據Start with “Why” - Why do we do the work we do?從“為什么”開始-我們為什么要做我們所做的工作&#xff1f; The question of “Why” is always a big question. Plus, it always makes you look smart in a meeting!“ 為什么 ”的問題始終是…

C語言中局部變量和全局變量 變量的存儲類別

C語言中局部變量和全局變量 變量的存儲類別(static,extern,auto,register) 局部變量和全局變量在討論函數的形參變量時曾經提到&#xff0c;形參變量只在被調用期間才分配內存單元&#xff0c;調用結束立即釋放。這一點表明形參變量只有在函數內才是有效的&#xff0c;離開該函…

營銷 客戶旅程模板_我如何在國外找到開發人員的工作:我從營銷到技術的旅程...

營銷 客戶旅程模板by Dimitri Ivashchuk由Dimitri Ivashchuk 我如何在國外找到開發人員的工作&#xff1a;我從營銷到技術的旅程 (How I got a developer job abroad: my journey from marketing to tech) In this post, I’ll go into the details of how I, a Ukrainian mar…

keepalive的作用

keepalive的作用是實現高可用,通過VIP虛擬IP的漂移實現高可用.在相同集群內發送組播包,master主通過VRRP協議發送組播包,告訴從主的狀態. 一旦主掛了從就選舉新的主,實現高可用 LVS專屬技能,通過配置文件控制lvs集群節點.對后端真實服務器進行健康檢查. 轉載于:https://www.cnb…

scrapy.Spider的屬性和方法

scrapy.Spider的屬性和方法 屬性: name:spider的名稱,要求唯一 allowed_domains:允許的域名,限制爬蟲的范圍 start_urls:初始urls custom_settings:個性化設置,會覆蓋全局的設置 crawler:抓取器,spider將綁定到它上面 custom_settings:配置實例,包含工程中所有的配置變量 logge…

php時間操作函數總結,基于php常用函數總結(數組,字符串,時間,文件操作)

數組:【重點1】implode(分隔,arr) 把數組值數據按指定字符連接起來例如&#xff1a;$arrarray(1,2,3,4);$strimplode(-,$arr);explode([分隔],arr)按指定規則對一個字符串進行分割&#xff0c;返回值為數組 別名joinarray_merge()合并一個或多個數組array_combine(array keys, …

kaggle比賽數據_表格數據二進制分類:來自5個Kaggle比賽的所有技巧和竅門

kaggle比賽數據This article was originally written by Shahul ES and posted on the Neptune blog.本文最初由 Shahul ES 撰寫&#xff0c; 并發布在 Neptune博客上。 In this article, I will discuss some great tips and tricks to improve the performance of your stru…

leetcode 1579. 保證圖可完全遍歷(并查集)

Alice 和 Bob 共有一個無向圖&#xff0c;其中包含 n 個節點和 3 種類型的邊&#xff1a; 類型 1&#xff1a;只能由 Alice 遍歷。 類型 2&#xff1a;只能由 Bob 遍歷。 類型 3&#xff1a;Alice 和 Bob 都可以遍歷。 給你一個數組 edges &#xff0c;其中 edges[i] [typei,…

別把“運氣”當“實力”

成功是兩分靠努力&#xff0c;八分靠天命–何英圻何英圻先生&#xff0c;大家口中的Steven&#xff0c;是臺灣網路創業圈的傳奇人物。他先后創辦力傳(Ubid)與興奇(Monday)兩家公司&#xff0c;最后都以高價出售給北美網路巨人—Ubid在2002年以美金950萬賣給eBay&#xff0c;而M…

品牌推廣前期要進行哪些針對性的步驟?

企業在品牌推廣前需要制訂一系列有針對性和連續性的步驟&#xff0c;這些步驟定睛于長期策略&#xff0c;而且要適應目標客戶的使用方式和習慣。在企業內部導入品牌VI是前提&#xff0c;外部的宣傳則是強調品牌所宣揚的內涵和精神實質&#xff0c;總體來說&#xff0c;這只是一…