1. 程式人生 > >effective java(3) 之用私有構造器或者列舉型別強化Singleton屬性

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

effective java 之用私有構造器或者列舉型別強化Singleton屬性
實現單例模式通常有3種方法(詳細請看設計模式單例模式一節)
Singleton指僅僅被例項化一次的類。
私有建構函式只能在函式內部呼叫,外部不能例項化,所以私有建構函式可以防止該類在外部被例項化。
1.靜態成員
public class Aagersingleton {
private static final Aagersingleton m_instance = new Aagersingleton();
// 私有預設構造方法
private Aagersingleton() {
}
//普通方法
public void method() {
System.out.println("餓漢式單例類,通過靜態工廠呼叫!");
}
}
public static void main(String[] args) {
Aagersingleton instance1 = Aagersingleton.m_instance;
instance1.method();
}

2.靜態工廠方法
//餓漢式單例類
public class Aagersingleton {
private static final Aagersingleton m_instance = new Aagersingleton();

// 私有預設構造方法
private Aagersingleton() {
}
// 靜態工廠方法
public static Aagersingleton getInstance() {
return m_instance;
}
//普通方法
public void method() {
System.out.println("餓漢式單例類,通過靜態工廠呼叫!");
}
}
public static void main(String[] args) {

Aagersingleton instance1 = Aagersingleton.getInstance();
instance1.method();
}

但是這兩種方法不能保證全域性只有一個物件。
可以通過反射機制,設定AccessibleObject.setAccessible(true),改變構造器的訪問屬性,呼叫構造器生成新的例項。

Constructor<?> constructor = Aagersingleton.class.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Aagersingleton instance2 = (Aagersingleton) constructor.newInstance();
instance2.method();

例項化count=0次
餓漢式單例類,通過靜態工廠呼叫!
例項化count=1次
餓漢式單例類,通過靜態工廠呼叫!
可以看出例項化兩次,不能保證全域性只有一個物件。

解決方案:
public class Aagersingleton {
private static int count = 0;
public static final Aagersingleton m_instance = new Aagersingleton();

// 私有預設構造方法
private Aagersingleton() {
System.out.println("例項化count="+count+"次");
if (count > 0) {
throw new IllegalArgumentException(
"Cannot create Aagersingleton twice");
}
count++;
}

// 靜態工廠方法
public static Aagersingleton getInstance() {
return m_instance;
}

// 普通方法
public void method() {
System.out.println("餓漢式單例類,通過靜態工廠呼叫!");
}
}
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Aagersingleton instance1 = Aagersingleton.m_instance;
instance1.method();

Constructor<?> constructor = Aagersingleton.class.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Aagersingleton instance2 = (Aagersingleton) constructor.newInstance();
instance2.method();
}

例項化count=0次
餓漢式單例類,通過靜態工廠呼叫!
例項化count=1次
Exception in thread "main" java.lang.reflect.InvocationTargetException
第二次例項化報錯,保證全域性只有一個物件。

如果上面兩種方法實現的Singleton是可以序列化的,加上 implements Serializable只保證它可以序列化。
為了保證反序列化的時候,例項還是Singleton,必須宣告所有的例項域都是transient的,並且提供 readResolve方法,否則,每次反序列化都會生成新的例項。

private Object readResolve() {
        return m_instance;
    }

3.單元素列舉型別

public enum Aagersingleton1 {
m_instance;


// 普通方法
public void method() {
System.out.println("餓漢式單例類,通過靜態工廠呼叫!");
}
}
public class Test2 {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Aagersingleton1 instance1 = Aagersingleton1.m_instance;
instance1.method();


Constructor<?> constructor = Aagersingleton1.class.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Aagersingleton1 instance2 = (Aagersingleton1) constructor.newInstance();
instance2.method();
}
}

通過列舉實現Singleton更加簡潔,同時列舉型別無償地提供了序列化機制,可以防止反序列化的時候多次例項化一個物件。
列舉型別也可以防止反射攻擊,當你試圖通過反射去例項化一個列舉型別的時候會丟擲IllegalArgumentException異常

所以單元素的列舉型別是實現Singleton的最佳方法。

每天努力一點,每天都在進步。

相關推薦

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

讀書筆記-《Effective Java》第3條、第4條: 強化Singleton屬性私有構造或者列舉型別

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

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

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

使用私有構造方法或者列舉型別實現單例

單例(Singleton)是指只例項化一次的類。 單例表示本質上唯一的系統元件,例如檔案系統或者視窗管理器。 package com.googlecode.javatips4u.effectivejava.singleton; publicclass StaticFin

Effective Java 第三版讀書筆記——條款3:使用私有構造來強制實現不可例項化

偶爾你會想寫一個類,這個類只是一組靜態方法和靜態屬性。 這樣的類獲得了不好的名聲,因為有些人濫用這些類而避免以面向物件的方式思考,但是它們有時候確實有實際的用處: 它們可以被用來聚集一組建立在基礎型別或陣列之上的相關方法,例如 java.lang.Math