1. 程式人生 > >單元素的列舉型別已經成為實現Singleton的最佳方法

單元素的列舉型別已經成為實現Singleton的最佳方法

一、概述

Singleton模式是在程式設計實踐中應用最廣泛的幾種設計模式之一。以前常用的是下面的這種方法:

public class Singleton
{
    private volatile static Singleton instance;

    private Singleton(){};

    public static Singleton getInstance()
    {
        if (instance == null)
        {
            synchronized (Singleton.class)
            {
                if
(instance == null) { instance = new Singleton(); } } } return instance; } }

這種方法稱為雙重校驗鎖,極不推薦使用。

二、其他實現Singleton的方法

1、餓漢式:

public class Singleton
{
    public static final Singleton INSTANCE = new Singleton();
    private
Singleton(){}; }

2、餓漢式變種(1)

public class Singleton
{
    private static final Singleton INSTANCE = new Singleton();
    private Singleton(){};
    public static Singleton getInstance()
    {
        return INSTANCE;
    }
}

這兩種方式都要求使用私有構造器,私有構造器僅被呼叫一次,用來例項化靜態final域Singleton.INSTANCE。

3、餓漢式變種(2) 類初始化的時候例項化instance

public class Singleton
{
    private static Singleton instance = null;
    private Singleton(){};
    static
    {
        instance = new Singleton();
    }

    public static Singleton getInstance()
    {
        return instance;
    }
}

4、靜態內部類

public class Singleton
{
    private static class SingletonHolder
    {
        private static final Singleton instance = new Singleton();
    }
    private Singleton(){};

    public static Singleton getInstance()
    {
        return SingletonHolder.instance;
    }
}

這四種方法都可以藉助AccessibleObject.setAccessible方法,通過反射機制,呼叫私有構造器建立新的例項,如下圖:
這裡寫圖片描述

可見s1 == s2為fasle,說明建立了兩個例項,也用失去了Singleton屬性。如果需要抵禦這種攻擊,可以修改構造器,讓它在被要求建立第二個例項的時候丟擲異常。

三、使用單元素的列舉實現Singleton

public enum Singleton
{
    INSTANCE;

    public void dosomething()
    {
        System.out.println(this + " is speaking!");
    }
}

先看下執行後的結果:
這裡寫圖片描述

這裡寫圖片描述

使用單元素的列舉型別實現Singleton時,通過反射機制去建立新的例項時會丟擲異常。

和以前的s1 == s2對比,可以看到使用單元素的列舉型別在功能上與公有域方法相近,但是它更加簡潔,並且無償得提供了序列化機制,絕對防止多次例項化。