1. 程式人生 > >第3條:用私有構造器或者列舉型別強化Singleton屬性

第3條:用私有構造器或者列舉型別強化Singleton屬性

術語:

Singleton:指僅僅被例項化一次的類。

        Singleton會使它的客戶端測試變得十分困難,因為無法給Singleton替換模擬實現,除非它實現一個充當其型別的介面。

        實現Singleton有以下三種方法:

1、實現公有靜態成員函式,並將之設定為final。例如

// Singleton with public field
public class Elvis {
	public static final Elvis INSTANCE = new Elvis();
	private Elvis() { ... }
	
	public void leaveTheBuilding() { ... }
}
        這種方法把建構函式私有化,這樣保證了Elvis的全域性唯一性。但有一個問題,就是享有特權的客戶端可能借助AccessibleObject.setAccessible方法,通過反射機制呼叫私有構造器,這樣就破壞了Singleton,一種補救的辦法是,修改構造器讓他被要求生成第二個例項的時候丟擲異常。

2、例項私有化,但通過公有的靜態方法返回,例如

public class Elvis {
	private static final Elvis INSTANCE = new Elvis();
	private Elvis() { ... }
	public static Elvis getInstance() { return INSTANCE;  }
	
	public void leaveTheBuilding() { ... }
}
        對於靜態方法Elvis.getInstance的所有呼叫都會返回同一個物件的引用,這樣就保證了唯一性,但是還是存在第1種方法裡的反射機制進行攻擊的問題。

        第一種方法的好處在於組成類的成員的宣告很清楚的表明了這是類的一個Singleton,但是相比之下不再比第二種方法有什麼優勢,因為JVM幾乎都將靜態工廠方法的呼叫內聯化。第二種方法的優勢之一在於,它提供了靈活性,在不改變其API的前提下,可以改變該類是否應該是Singleton的想法,這種方法可以很容易的被修改成按不同需求返回相應的唯一例項。第二個優勢在於與泛型有關,但是相比之下,第一種方法更為簡單。

        以上兩種方法還有一個問題,就是在實現Singleton類序列化的時候,僅僅在聲名中加上“implement Serializable”是不夠的。為了維護並保證Singleton,必須聲名所有的例項都是瞬時的(transient),並提供一個readResolve方法。否則的話每次反序列化的時候都會建立一個新的例項,這個時候要加入以下程式碼

// readResolve method to preserve singleton property
private Object readResolve() {
	// Return the one true Elvis and let the garbage collector
	// take care of the Elvis impersonator
	return INSTANCE;
}
3、包含單個元素的列舉型別。
public enum Elvis {
	INSTANCE;
	
	public void leaveTheBuilding() { ... }
}
        這種方法更加簡潔,無償的提供了序列化機制,絕對防止多次例項化(由Enum保證),即使是在面對複雜的序列化或者反序列化或者反射攻擊的時候也可以保證唯一。這已成為實現 Singleton的最佳方法。

相關推薦

3私有構造或者列舉型別強化Singleton屬性

術語: Singleton:指僅僅被例項化一次的類。         Singleton會使它的客戶端測試變得十分困難,因為無法給Singleton替換模擬實現,除非它實現一個充當其型別的介面。         實現Singleton有以下三種方法: 1、實現公有靜態成員

EffectiveJava 3 私有構造或者列舉型別強化Singleton屬性

Singleton只不過是指僅僅例項化一次的類[Gamma95, p. 127]。Singleton通常被用來代表那些本質上唯一的系統元件,比如視窗管理器或者檔案系統。使類成為Singleton會使它的客戶端測試變得十分困難,因為無法給Singleton替換模擬實現,除非

Effective java私有構造或者列舉型別強化singleon屬性

單例模式大家都不模式,java1.5發行版之前大家都用兩種方法實現singleton。 第一種:靜態成員 public class Singleton1 { public static final Singleton1 INSTANCE =

3私有構造或者列舉型別強化Singleton屬性

在java 1.5版本發行前實現單例一般有兩種方法 (1)靜態成員 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() {

3私有構造或者列舉型別強化Singleton屬性

一、公有final域靜態成員 //Singleton with public final field public class Elvis { public static final Elvi

3 建立與銷燬物件——私有構造或者列舉型別強化Singleton屬性

實現Singleton有以下三種方法。 1、將公有靜態成員做成final域: public class Elvis { public static final Elvis INSTANCE = newElvis(); private Elvis() {

3:私有構造或者列舉型別強化Singleton屬性

Singleton指僅僅被例項化一次的類。 例如:檔案系統,資料庫連線,視窗管理器等 在Java 1.5之前,實現Singleton有兩種方法,這兩種方法都要把構造器保持為私有的,下面直接貼例項程式碼,應該都能看懂: 第一種: 需要獲取的公有靜態成員(需

Effective Java 學習 私有構造或者列舉型別強化Singleton屬性

綜述:Singleton即單例模式是指僅僅被例項化一次的類。比如工作管理員、檔案管理器、回收站、某些工具類等,這些類在程式中僅僅需要一個例項就足夠了,這個時候可以考慮使用單例模式。,以下介紹三種實現單例模式的方法: 1.餓漢式(類載入時建立例項) /** * Create

effective java(3) 之私有構造或者列舉型別強化Singleton屬性

effective java 之用私有構造器或者列舉型別強化Singleton屬性 實現單例模式通常有3種方法(詳細請看設計模式單例模式一節)Singleton指僅僅被例項化一次的類。私有建構函式只能在函式內部呼叫,外部不能例項化,所以私有建構函式可以防止該類在外部被例項

3私有構造或者列舉型別強化SIngleton屬性

結論 單元素的列舉型別已經成為實現Singleton的最佳方法 Singleton模式 常見的Singleton有兩種方式,第一種: public class Elvis { /

私有構造或者列舉型別強化Singleton屬性

        Singleton指僅僅被例項化一次的類。         Singleton通常被用來代表那些本質上唯一的系統元件,比如視窗管理器或者檔案系統。使類成為Singleton會使它的客戶端測試變得十分困難,因為無法給Singleton替換模擬實現,除非它實現一

私有構造或者列舉型別強化Singleton屬性

在java1.5版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有的,並匯出公有的靜態成員,一遍允許客戶端能夠訪問該類的唯一例項。在第一種方法中,公有靜態成員是個final域: public class Elvis{ pu

《Effective Java》私有構造或者列舉型別強化SingleTon屬性

我們耳熟能詳的單例有懶漢式、餓漢式等 例如下面這段的餓漢式 用private修飾構造方法,防止外界通過無參的構造方法直接建立物件,但是這樣還是可以通過反射來攻擊,造成程式碼的不安全,可以考慮設定一個變數,在建立第二個物件的時候丟擲一個自定義的異常。 這

私有構造或者列舉型別強化Singleton屬性-03

術語: Singleton:指僅僅被例項化一次的類。         Singleton會使它的客戶端測試變得十分困難,因為無法給Singleton替換模擬實現,除非它實現一個充當其型別的介面。         實現Singleton有以下三種方法:

私有構造列舉型別強化Singleton屬性

單例 Singleton 指僅僅被例項化一次的類,Singleton 通常被用來代表本質上唯一的系統元件 實現Singleton有兩種方法,兩種方法都要把構造器私有化 並匯出公有的靜態成員. 1. public class Elvis{ public static fi

Effective Java 建立和銷燬物件 3.私用構造或者列舉型別強化Singleton屬性

Singleton 也就是常說的單例模式,只能被例項化一次,當然這看操作。 java1.5版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有的,並匯出公有的靜態成員,一遍允許客戶端能夠訪問該類的唯一例項。在第一種方法中,公有靜態成員是個final域

讀書筆記-《Effective Java》34 強化Singleton屬性私有構造或者列舉型別

第3條:用私有構造器或者列舉型別強化Singleton屬性 把構造器私有這個是單例基本要求,本條介紹了一種不知道為啥沒有流行起來的單例方式(實現Singleton的最佳方式),包含單個元素的列舉型別(INSTANCE不是關鍵字,寫別的也行) package org.test; p

《Effective Java 中文版 2版》學習筆記 4通過私有構造強化不可實例化的能力

缺省 ive ont sof family 其他 筆記 cnblogs ror   只有當類不包含顯式的構造器時,編譯器才會生成一個公有的、無參的缺省構造器。只要讓一個類包含私有構造器,這個類就不能被實例化了。示例: 1 // 工具類 2 public class Uti

Effective Java 三版讀書筆記——條款3使用私有構造列舉型別來強制實現 singleton 屬性

單例(singleton)就是一個只例項化一次的類。使類成為單例可能會使它的測試變得困難,因為除非它實現了作為其型別的介面,否則不可能用模擬實現來代替這個單例。下面是幾種實現單例的方法: 使用 public field 方法 // Singleton with public final field pub

4通過私有構造強化不可例項化的能力

對只有靜態方法和域的類,主要用於把基本型別的值或資料型別上的相關方法組織起來(Math,Arrays),可以通過Collections的方法把實現特定介面的物件上的驚天方法組織起來,可以利用這種類把final類上的方法組織起來,以取代擴充套件該類的做法。此工具類