單例模式比較常見的實現方法有懶漢模式,DCL模式公有靜態成員等,從Java 1.5版本起,單元素枚舉實現單例模式成爲最佳的方法。java
枚舉的用法比較多,本文主要旨在介紹利用枚舉實現單例模式的原理,因此這裏也主要介紹一些相關的基礎內容。
首先,枚舉相似類,一個枚舉能夠擁有成員變量,成員方法,構造方法。先來看枚舉最基本的用法:數據庫
enum Type{
A,B,C,D;
}
建立enum時,編譯器會自動爲咱們生成一個繼承自java.lang.Enum的類,咱們上面的enum能夠簡單看做:網絡
class Type extends Enum{ public static final Type A; public static final Type B; ... }
對於上面的例子,咱們能夠把Type看做一個類,而把A,B,C,D看做類的Type的實例。
固然,這個構建實例的過程不是咱們作的,一個enum的構造方法限制是private的,也就是不容許咱們調用。ide
上面說到,咱們能夠把Type看做一個類,而把A,B。。。看做Type的一個實例。一樣,在enum中,咱們能夠定義類和實例的變量以及方法。看下面的代碼:spa
enum Type{ A,B,C,D; static int value; public static int getValue() { return value; } String type; public String getType() { return type; } }
在原有的基礎上,添加了類方法和實例方法。咱們把Type看作一個類,那麼enum中靜態的域和方法,均可以視做類方法。和咱們調用普通的靜態方法同樣,這裏調用類方法也是經過 Type.getValue()便可調用,訪問類屬性也是經過Type.value便可訪問。 下面的是實例方法,也就是每一個實例才能調用的方法。那麼實例是什麼呢?沒錯,就是A,B,C,D。因此咱們調用實例方法,也就經過 Type.A.getType()來調用就能夠了。 最後,對於某個實例而言,還能夠實現本身的實例方法。再看下下面的代碼: 線程
enum Type{ A{ public String getType() { return "I will not tell you"; } },B,C,D; static int value; public static int getValue() { return value; } String type; public String getType() { return type; } }
這裏,A實例後面的{…}就是屬於A的實例方法,能夠經過覆蓋本來的方法,實現屬於本身的定製。 blog
除此以外,咱們還能夠添加抽象方法在enum中,強制ABCD都實現各自的處理邏輯:繼承
enum Type{ A{ public String getType() { return "A"; } },B { @Override public String getType() { return "B"; } },C { @Override public String getType() { return "C"; } },D { @Override public String getType() { return "D"; } }; public abstract String getType(); }
有了上面的基礎,咱們能夠來看一下枚舉單例的實現方法:資源
class Resource{ } public enum SomeThing { INSTANCE; private Resource instance; SomeThing() { instance = new Resource(); } public Resource getInstance() { return instance; } }
上面的類Resource是咱們要應用單例模式的資源,具體能夠表現爲網絡鏈接,數據庫鏈接,線程池等等。 get
獲取資源的方式很簡單,只要 SomeThing.INSTANCE.getInstance() 便可得到所要實例。下面咱們來看看單例是如何被保證的:
首先,在枚舉中咱們明確了構造方法限制爲私有,在咱們訪問枚舉實例時會執行構造方法,同時每一個枚舉實例都是static final類型的,也就代表只能被實例化一次。在調用構造方法時,咱們的單例被實例化。
也就是說,由於enum中的實例被保證只會被實例化一次,因此咱們的INSTANCE也被保證明例化一次。
能夠看到,枚舉實現單例仍是比較簡單的,除此以外咱們再來看一下Enum這個類的聲明:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable
能夠看到,枚舉也提供了序列化機制。某些狀況,好比咱們要經過網絡傳輸一個數據庫鏈接的句柄,會提供不少幫助。
最後借用 《Effective Java》一書中的話,
單元素的枚舉類型已經成爲實現Singleton的最佳方法。