原文地址:https://zhuanlan.zhihu.com/p/...html
一、什麼是單例模式?java
百度百科是這樣定義的:單例模式是一種經常使用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例的特殊類。經過單例模式能夠保證系統中一個類只有一個實例設計模式
我是這樣理解的:單例模式就是隻容許一個實例,最開始使用它的時候是C#中,我要實例化一個A窗體,可是有個需求就是A窗體必須是惟一,無論我在B窗體操做A窗體仍是C窗體中操做A窗體都是如此,這時候就使用到了單例模式安全
二、單例模式分類併發
A、懶漢單例模式:在第一次調用的時候實例化自己,在併發環境下,可能出現多個自己對象。因此線程是不安全的函數
B、餓漢單例模式:在類初始化時,已經自行實例化一個靜態對象,因此自己就是線程安全的性能
C、登記單例模式:經過一個專門的類對各單例模式的單一實例進行管理和維護學習
三、特色編碼
A、 單例模式類只能有一個實例
B、 單例模式類必須本身建立本身的惟一實例
C、 單例模式類必須給全部其餘對象提供這一實例.net
一、懶漢單例模式
/** * 描述:懶漢單例模式<p> * 做者: kimball <p> * E-mail: kimballlu@foxmail.com <p> * 日期:2016-11-16 下午4:30:32 <p> */ public class Singleton { /** * 該函數限制用戶主動建立實例 */ private Singleton() {} private static Singleton singleton = null; /** * 獲取Singleton實例(也叫靜態工廠方法) * @return Singleton */ public static Singleton getSingleton() { /* 當singleton爲空時建立它,反之直接返回,保證惟一性 */ if(singleton == null){ singleton = new Singleton(); } return singleton; } }
線程安全的懶漢單例模式
在getSingleton()添加synchronized同步
/** * 描述:懶漢單例模式,在getSingleton()方法添加同步<p> * 做者: kimball <p> * E-mail: kimballlu@foxmail.com <p> * 日期:2016-11-16 下午4:30:32 <p> */ public class Singleton { /** * 該函數限制用戶主動建立實例 */ private Singleton() {} private static Singleton singleton = null; /** * 獲取Singleton實例,也叫靜態工廠方法 * @return Singleton */ public static synchronized Singleton getSingleton(){ if(singleton==null){ singleton=new Singleton(); } return singleton; } }
雙重檢查鎖定
ps:已修正,仍不推薦使用,感謝
江南布衣
指正
具體可參考正確使用雙重檢查鎖定和雙重檢驗鎖失效」的問題說明
/** * 描述:懶漢單例模式 ,雙重檢查鎖定<p> * 做者: kimball <p> * E-mail: kimballlu@foxmail.com <p> * 日期:2016-11-16 下午4:30:32 <p> */ public class Singleton { /** * 該函數限制用戶主動建立實例 */ private Singleton() {} private volatile static Singleton singleton = null; /** * 獲取Singleton實例,也叫靜態工廠方法 * @return Singleton */ public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
靜態內部類:靜態內部類比雙重檢查鎖定和在getInstance()方法上加同步都要好,實現了線程安全又避免了同步帶來的性能影響
/** * 描述:懶漢單例模式 ,靜態內部類<p> * 做者: kimball <p> * E-mail: kimballlu@foxmail.com <p> * 日期:2016-11-16 下午4:30:32 <p> */ public class Singleton { /** * 靜態內部類 * @author kimball * */ private static class LazyHolder { // 建立Singleton實例 private static final Singleton INSTANCE = new Singleton(); } /** * 該函數限制用戶主動建立實例 */ private Singleton() {} /** * 獲取Singleton實例,也叫靜態工廠方法 * @return Singleton */ public static final Singleton getInstance() { return LazyHolder.INSTANCE; } }
二、餓漢單例模式
/** * 描述:餓漢單例模式<p> * 做者: kimball <p> * E-mail: kimballlu@foxmail.com <p> * 日期:2016-11-16 下午4:30:32 <p> */ public class Singleton { /** * 該函數限制用戶主動建立實例 */ private Singleton() {} private static final Singleton singleton = new Singleton(); /** * 獲取Singleton實例,也叫靜態工廠方法 * @return Singleton */ public static Singleton getInstance() { return singleton; } }
三、登記單利模式
/** * 描述:登記單例模式<p> * 做者: kimball <p> * E-mail: kimballlu@foxmail.com <p> * 日期:2016-11-16 下午4:30:32 <p> */ public class Singleton { // 存儲須要進行維護和管理的類的實例 private static Map<String, Singleton> map = new HashMap<String, Singleton>(); /** * 靜態建立實例並添加到Map集合 */ static { Singleton singleton = new Singleton(); map.put(singleton.getClass().getName(), singleton); } /** * 該函數限制用戶主動建立實例 */ private Singleton() {}; /** * 獲取Singleton實例,也叫靜態工廠方法 * @return Singleton */ public static Singleton getInstance(String name) { /* 根據指定的類的名稱從mao中獲取實例並返回 */ return map.get(name); } // 一個示例性的商業方法 public String about() { return "你好,我是RegSingleton"; } public static void main(String[] args) { Singleton singleton = Singleton.getInstance("com.Singleton"); System.out.println(singleton.about()); } }
以上就是單例設計模式,雖然單例設計模式是23種設計模式種比較簡單的設計模式。可是三個臭皮匠也能頂一個諸葛亮,它天然有它存在的道理。
設計模式說白點就是編碼的一種思惟(以前在學校老師一個勁兒的說思惟思惟,如今我也開始說,手動滑稽)
我是以生活的角度去看待編碼,編碼就是世界的縮小版
上述講的幾種單例模式實現中,有一種狀況下他們會從新建立對象,那就是反序列化,將一個單例實例對象寫到磁盤再讀回來,從而得到了一個實例。反序列化操做提供了readResolve方法,這個方法可讓開發人員控制對象的反序列化。在上述的幾個方法示例中若是要杜絕單例對象被反序列化是從新生成對象,就必須加入以下方法:
private Object readResolve() throws ObjectStreamException{ return singleton; }
以上摘自https://blog.csdn.net/itachi8...
**一、因爲enum是經過繼承了Enum類實現的,enum結構不可以做爲子類繼承其餘類,可是能夠用來實現接口。此外,enum類也不可以被繼承。
二、enum有且僅有private的構造器,防止外部的額外構造**
補充一種枚舉實現的單例模式。
public enum SingletonEnum { INSTANCE; }
這樣就實現完了,調用以下
@Test void singleton(){ SingletonEnum instance = SingletonEnum.INSTANCE; }
對於序列化和反序列化,由於每個枚舉類型和枚舉變量在JVM中都是惟一的,即Java在序列化和反序列化枚舉時作了特殊的規定,枚舉的writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法是被編譯器禁用的,所以也不存在實現序列化接口後調用readObject會破壞單例的問題。
以上摘自https://www.cnblogs.com/cielo...
若是文章對您有幫助,請記得點贊關注喲~ 歡迎你們關注個人公衆號<情繫IT>,每日推送技術文章供你們學習參考。