請實現單例模式

要點

  1. 某個類只能有一個實例
    • 構造器私有化
  2. 它必須自行建立這個實例
    • 含有一個該類的靜態變量來保存這個惟一實例
  3. 必須自行先整個系統提供這個實例
    • 對外提供獲取該實例對象的方式
      1. 直接暴露
      2. 用靜態變量的 get 方法獲取

常見幾種形式

  • 餓漢式:直接建立對象不存在線程安全問題
    • 直接實例化餓漢式(簡潔直觀)
    • 枚舉式(最簡潔)
    • 靜態代碼塊餓漢式(適合複雜實例化)
  • 懶漢式:延遲建立對象
    • 線程不安全(適用於單線程)
    • 線程安全(適用於多線程)
    • 靜態內部列形式(適用於多線程)
  1. 直接實例化對象,無論是否須要這個對象-餓漢式
/*
* 餓漢式
*(1)構造器私有化
*(2)自行建立,並用靜態變量保存
*(3)向外提供這個實例
*(4)強調這是單例,用final修飾(這個變量只能賦值一次,以後不能修改)
*/
public class Singleton1 {
    public static final Singleton1 INSTANCE = new Singleton1();
    private Singleton1 (){
        
    }
}
  1. 枚舉-jdk1.5以後-餓漢式
/*
*餓漢式
*枚舉類型:表示該類型的對象是有限的幾個
*咱們能夠限定爲一個,就成了單例
*/
public enum Singleton2{
    INSTANCE
}
  1. 靜態代碼塊-餓漢式
/*
* 這種方式,適合那種須要從配置文件裏面讀一堆信息來實例化。
*/
public class Singleton3 {
    public static final Singleton3 INSTANCE;
    private String info;
    static {
        try {
            Properties pro = new Properties(); // 從位於src目錄下的配置文件single.properties中讀取信息
            pro.load(Sinfleton3.class.getClassLoader().getResourceAsStream("single.properties"));
            INSTANCE = new Singleton3(pro.getPropertied("info"));
        }catch(IOExcepption e){
            throw new RuntimeException(e);
        }
    }
    private Singleton3 (String info){
        this.info = info;
    }
}

4.線程不安全(適合單線程)-懶漢式安全

/*
* 懶漢式
*(1)構造器私有化
*(2)靜態變量保存
*(3)提供一個靜態方法,獲取實例對象
*/
public class Singleton4 {
    private static Singleton4 instance;
    private Singleton4 (){
        
    }
    public static Singleton4 getInstance(){
        if(instance == null){
            //加上Thread.sleep(100);多線程狀況下 會實例化兩個對象。
            instance = new Singleton4();
        }
        return instance;
    }
}
  1. 線程安全(適合多線程)-懶漢式
/*
* 懶漢式
*(1)構造器私有化
*(2)靜態變量保存
*(3)提供一個靜態方法,獲取實例對象
*/
public class Singleton5 {
    private static Singleton5 instance;
    private Singleton5 (){
        
    }
    public static Singleton5 getInstance(){
        if(instance == null){//先判斷是否爲空,再進行加鎖。
            synchronized(Singleton5.class){
                //加上Thread.sleep(100);多線程狀況下 會實例化兩個對象。
                instance = new Singleton5();
            }
        }
        return instance;
    }
}
  1. 靜態內部類形式
/*
* 再內部類被加載和初始化時,才建立INSTANCE實例對象
* 靜態內部類不會自動隨着外部類的加載和初始化而初始化,它是要單獨去加載和初始化的
* 由於是在內部類加載和初始化是,建立的,所以是線程安全的。
*/
public class Singleton6 {
    
    private Singleton6 (){
        
    }
    private static class Inner{
        private static final Singleton6 INSTANCE = new Singleton6();
    }
    public static Singleton6 getInstance(){
        return Inner.INSTANCE;
    }
}
相關文章
相關標籤/搜索