開發之路(設計模式五:單件模式)

擁有獨立且惟一的對象

此次講述的是單件模式,就是整個內容裏只有一個實例化「惟一」對象。這麼說可能有點拗口,這麼說吧,比方說,線程池,緩存,註冊表,日誌文件,甚至作JDBC中鏈接,關閉,增刪改查數據庫的Connection類(我的命名也許並不同)、工具類等等。這些東西每每是要實例一次,就能在整個項目中使用了。java

單件模式並不難理解定義以下
單件模式:確保一個類中只有一個實例,並提供一個全局訪問點。
是的就這麼一句話的定義。通常單件模式分爲「懶漢式」和「餓漢式」作法數據庫

直接上代碼。編程

「懶漢式」作法設計模式

package singleton01;

public class Singleton01 {
    // 利用一個靜態變量記錄本類當中惟一的實例(mySingleton01)
    private  static Singleton01 mySingleton01 = null;

    public Singleton01() {
    }

    // synchronized關鍵字:線程同步鎖,在多線程中去互斥地訪問臨界資源
    // 迫使每一個線程在進入方法以前,要先等別的線程執行完離開方法後才能執行,達到多個線程排隊,不會形成有多個線程同時進入這個方法
    // 便是同步。但同步會使程序效率下降
    public static synchronized Singleton01 getInstance() {
        if (mySingleton01 == null) {
            mySingleton01 = new Singleton01();
            System.out.println("Singleton01被實例化了");
        }
        System.out.println("返回Singleton01實例");
        return mySingleton01;
    }
    /**
     * 上面方法就是常說了「懶漢式」作法,大致意思就是當誰須要類方法時採起實例化
     */
}
package singleton01;

public class TestMain {
    public static void main(String[] args) {
        // 打印出前兩行結果
        Singleton01 singleton01 = Singleton01.getInstance();

        // 此時咱們看到第二次調用類方法時候,沒有去實例對象
        // 這裏涉及併發方面問題,暫時沒學習併發,具體怎麼個原理我也不知道...
        Singleton01 singleton02 = Singleton01.getInstance();
    }
}

效果圖1
圖片描述緩存

效果圖2
圖片描述多線程

以前的作法中咱們用到了synchronized,就是爲了防止線程啓動的隨機性找出變量混亂,我這個小例子可能看不出來什麼。但實際上同步線程(synchronized)會使得程序效率大幅下降。利用雙重檢查加鎖能夠有效解決此問題,併發

使用雙重檢查加鎖工具

package singleton01;

public class singleton02 {
    // 利用雙重檢查加鎖,先檢查實例是否已經建立,若是沒建立,就進行同步。
    // volatile:instance變量被初始化singleton02實例時,多個線程會正確處理instance變量
    // 線程是具備隨機性的,與程序執行順序無關。
    private volatile static singleton02 instance=null;

    public singleton02() {        
    }

    public static singleton02 getInstance() {
        if (instance == null) {
            // 檢查實例,不存在的話進入同步區域,只有第一次才執行這裏
            synchronized (singleton02.class) {
                System.out.println("進入同步區域");
                if (instance == null) {
                    System.out.println("instance被實例化了");
                    instance = new singleton02();
                }
            }
        }
        System.out.println("返回instance實例");
        return instance;
    }
}
package singleton01;

public class TestMain02 {
    public static void main(String[] args) {
        //第一次進入方法會進入同步區實例化
        singleton02 singleton02 = null;
        singleton02 = singleton02.getInstance();
        
        //當第二次進入時,已有實例,不會同步了,直接返回實例.
        singleton02 singleton03 = null;
        singleton03 = singleton02.getInstance();    
    }

}

效果圖
圖片描述學習

"餓漢式"作法spa

package singleton02;

public class Singleton {
    /**
     * 「餓漢式」:加載這個類時馬上建立本類中惟一的單件實例,
     */
    private static Singleton uniqueInstance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {
        System.out.println("返回實例實例");
        return uniqueInstance;
    }
}
package singleton02;

public class TestMain {
    public static void main(String[] args) {
        //直接返回實例
        Singleton singleton = Singleton.getInstance();
    }
}

效果圖
圖片描述

注:雙重檢查加鎖不適用與1.4以前的java版本。

要點:
一、單件模式確保程序中一個類最多隻有一個實例。
二、單件模式提供這個實例的全局訪問點。
三、實現單件模式,須要私有構造器,一個靜態方法,一個靜態變量。
四、設計到多線程問題,同步會下降程序效率。

感謝你看到這裏,至此單件模式內容結束,本人文筆隨便,如有不足或錯誤之處望給予指點,90度彎腰~~~很快我會發佈下一個設計模式內容,生命不息,編程不止!

參考書籍:《Head First 設計模式》
相關文章
相關標籤/搜索