設計模式總結 —— 單例設計模式

1、定義

      確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。數據庫

二。使用場景

      當對象須要消耗的資源過多(如訪問Io、數據庫等),避免產生多個對象消耗過多的資源,或者某種類型的對象只應該有且只有一個。安全

3、實現方法

(1)餓漢單例模式

      依靠靜態對象的初始化實現單例bash

public class Singleton{
    private static Singleton mInstance = new Singleton();
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance(){
        return mInstance;
    }
}
複製代碼

(2)懶漢單例模式

      第一次調用getInstance()後,單例對象就會被實例化。但每次調用getInstance()方法時都須要進行同步,會形成沒必要要的消耗。
      對於不頻繁調用getInstance()的狀況下,能夠適用。ui

public class Singleton{
    private static Singleton mInstance;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance(){
        if( mInstance == null){
            mInstance = new Singleton();
        }
        return mInstance;
    }
}
複製代碼

(3) Double Check Lock(DCL) 實現單例

public class Singleton{
    private volatile static Singleton mInstance;
    
    private Singleton() {}
    
    public static Singleton getInstance(){
        if( mInstance == null){
            synchronized(Singleton.class){
                if( mInstance == null){
                    mInstance = new Singleton();
                }
            }
        }
        return mInstance;
    }
}
複製代碼

      進行兩次判空,第一次判斷主要避免沒必要要的同步,第二次判斷主要爲了在同步狀況下確認單例仍爲空時,進行初始化。
spa

volatile關鍵字的做用:
      一、防止重排序
      new對象時,會進行三件事件:
            (1)、給Singleton的實例分配內存;
            (2)、調用Singleton()的構造方法,初始化成員變量。
            (3)、將mInstance對象指向分配的內存空間。
而在JVM中(2)和(3)的順序是沒法被保證的,只能經過volalite保證其有序性。
線程

      二、保證線程的可見性。
code

(4) 靜態內部類單例模型

依靠靜態內部類被使用時才被JVM加載的原理。對象

public class Singleton{
    private Singleton{}
    public static Singleton getInstance(){
        return SingletonHolder.mInstance;
    }
    
    //靜態內部類
    private static class SingletonHolder{
        private static final Singleton mInstance = new Singleton();
    }
}
複製代碼

靜態內部類和非靜態內部類加載時機的區別:
排序

      非靜態內部類,必定須要外部類實例化後纔會被加載。
事件

      靜態內部類的加載不須要依附外部類,在使用時才加載進。

(5) 使用容器實現單例。

將多種單例類型注入到一個統一的管理類中,使用時根據key獲取對應的單例對象。

public class SingletonManager{
    private static Map<String,Object> objMap = new HashMap<String,Object>();
    private SingletonManager{}
    
    public static void registerService(String key,Object instance){
        if(!object.containsKey(key)){
            objMap.put(key,instance);
        }
    }
    
    public static Object getService(String key){
        return objMap.get(key);
    }
}
複製代碼

(6) 枚舉單例

枚舉類型能夠定義本身的方法和本身的變量,並且枚舉實例的建立是線程安全的,而且任何狀況下都是單例。

public enum SingletonEnum{
    INSTANCE;
    public void doSomething(){
        System.out.println("do ");
    }
}
複製代碼
相關文章
相關標籤/搜索