設計模式詳解|單例模式

目錄

 

概述

適用場景  

優缺點

實現

餓漢式

懶漢式


概述

單例模式是一種創建型模式

許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行爲。比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息。這種方式簡化了在複雜環境下的配置管理。

適用場景  

  • 需要生成唯一序列的環境
  • 需要頻繁實例化然後銷燬的對象。
  • 創建對象時耗時過多或者耗資源過多,但又經常用到的對象。 
  • 方便資源相互通信的環境

優缺點

優點

  • 在內存中只有一個對象,節省內存空間;

  • 避免頻繁的創建銷燬對象,可以提高性能;

  • 避免對共享資源的多重佔用,簡化訪問;

  • 爲整個系統提供一個全局訪問點。

缺點

  •  不適用於變化頻繁的對象;

  • 濫用單例將帶來一些負面問題,如爲了節省資源將數據庫連接池對象設計爲的單例類,可能會導致共享連接池對象的程序過多而出現連接池溢出;

  • 如果實例化的對象長時間不被利用,系統會認爲該對象是垃圾而被回收,這可能會導致對象狀態的丟失;

實現

餓漢式

使用靜態變量來實現

public class EHan1 {
    //使用靜態變量,沒有線程安全問題,在類加載階段就已經進行
    private static EHan1 instance=new EHan1();
    private EHan1(){

    }
    //提供靜態方法,用方法而不用對象可以提供更好的封裝性。
    public static EHan1 getInstance(){
        return instance;
    }
}

使用靜態代碼塊來實現

public class EHan2 {
    //使用靜態變量,沒有線程安全問題,在類加載階段就已經進行
    private static EHan2 instance;
    private EHan2(){

    }
    static {
        instance=new EHan2();
    }
    //提供靜態方法,用方法而不用對象可以提供更好的封裝性。
    public static EHan2 getInstance(){
        return instance;
    }
}

枚舉

enum Singeleton{
    INSTANCE;
}
//屬於餓漢式方法
//是線程安全的
//不能被反射
//可以被反序列化
public class Enum {
    public static void main(String[] args) {
        Singeleton singeleton=Singeleton.INSTANCE;
    }
}

 

懶漢式

線程不安全

public class LHan1 {
    //線程不安全
    private static LHan1 instance;
    private LHan1(){

    }
    public LHan1 getInstance(){
        if(instance==null){
            instance= new LHan1();
        }
        return instance;
    }
}

雙重檢查(線程安全)

public class DoubleCheck {
    //線程安全
    //volatile 構造方法的指令和賦值指令有可能被重排序
    private static volatile DoubleCheck instance;
    private DoubleCheck(){

    }
    public static DoubleCheck getInstance(){
        if(instance==null){
            synchronized (DoubleCheck.class) {
                //防止首次創建時多個線程併發問題
                if(instance==null)
                    instance=new DoubleCheck();
            }
        }
        return instance;
    }
}

靜態內部類--線程安全

public class StaticInnerClass {
    //懶漢式 靜態內部類只有在類第一次被使用的時候纔會被裝載
    //volatile 構造方法的指令和賦值指令有可能被重排序
    private static volatile StaticInnerClass instance;
    private StaticInnerClass(){

    }
    //寫一個靜態內部類
    private static class StaticInnerInstace{
        private static final StaticInnerClass instace=new StaticInnerClass();
    }
    //提供一個靜態公有方法,直接返回成員變量
    public static synchronized StaticInnerClass getInstance(){
        return StaticInnerInstace.instace;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章