1. 程式人生 > >設計模式第五篇-單例模式

設計模式第五篇-單例模式

實例化 git 面試 turn 性能 垃圾 容易 調用 存在

一、引言

單例模式應該是設計模式中比較簡單的一個,因為這個模式只有一個類,但不要小看這個設計模式,這個模式可是面試的時候很常見的一個。

單例模式有什麽的用處:有一些對象我們只需要一個的時候,比如線程池,緩存,註冊表等。

也就是說這個模式的作用是:保證只有一個實例對象

二、單例模式

先看定義:確保一個類只有一個實例,並提供一個全局訪問點。

開始思考,我們如何確保只有一個實例?

首先要知道我們是如何創建的對象的,這個很容易回答:用new關鍵字,只要是公開類,我們在外部就可以無限的實例化,也是就說第一步就是要將類私有化。

如何私有化:使用私有構造構造器,一旦使用私有構造器,那麽外部便不能實例化。

可一旦使用私有構造器,那麽不是只有內部才能調用這個構造器麽?既然外部不能實例化,那麽如何去調用這個私有構造器呢?

這個時候靜態方法就起作用了,我們定義一個靜態方法,通過靜態方法去調用私有構造器,問題就解決了。

通過上面的思考,代碼就已經出來了:

//單例模式實現-懶漢式
public class Singleton {

    //利用靜態變量記錄類的唯一實例
    private static Singleton  uniqueInstance;
    //把構造器設置為私有,只有內部才可以調用構造器
    private Singleton(){}
    //用靜態方法實例化對象
    public static Singleton getInstance(){
        //如果為空則說明還沒有創建實例,這個時候我們可以創建,這個就是延時實例化,也就是傳說中的懶漢式
if(uniqueInstance==null){ uniqueInstance = new Singleton(); } return uniqueInstance; } public void showMsg(){ System.out.println("其他方法,顯示數據"); } }

這種實現方法叫做懶漢式,但這種懶漢模式存在一個問題:線程不安全,在多線程情況下,完全有可能生成多個實例,這個時候可以用synchronized關鍵字來處理。

 public static synchronized
Singleton getInstance(){ ... }

當然,加鎖會降低一些性能。

其實還有一種方法,那就是餓漢式

//單例模式-餓漢式
public class Singleton1 {
    //初始化器重直接創建,可以保證線程安全
    private static Singleton1 uniqueInstance=new Singleton1();
    //靜態方法
    private Singleton1(){}
    //直接返回
    public static Singleton1 getInstance(){
        return uniqueInstance;
    }
}

這樣的方式容易產生垃圾對象,浪費一些內存,但是沒有加鎖,效率提高很多(一般情況下推薦使用這種方式)。

另外還有一種凡是:雙重檢查加鎖

//雙重加鎖方式
public class Singleton2 {
    //利用volatile 關鍵字保證多個線程正確使用uniqueInstance
    private volatile  static Singleton2 uniqueInstance;
    private Singleton2(){}

    public static Singleton2 getInstance(){
        //檢查實例,不存在則進入同步代碼塊
        if(uniqueInstance==null){
            //同步代碼塊
            synchronized (Singleton2.class){
                //進入代碼塊後,再判斷一次
                if(uniqueInstance==null){
                    uniqueInstance=new Singleton2();
                }
            }
        }
        return uniqueInstance;
    }
}

這種方式可以大大提高性能,就是實現有些復雜(且不支持1.4之前的版本)

三、總結

單例模式是一個相對簡單的模式,主要的核心在私有化構造器,及暴露一個靜態方法創建實例,再考慮多線程相關情況。

設計模式相關源碼地址:https://gitee.com/yuanqinnan/pattern

設計模式第五篇-單例模式