設計模式學習筆記之單例模式

 

什麼是單例模式? html

顧名思義,就是隻有一個實例,也就是說一個應用程序中只有一個實例對象.java

既然一個系統,一個應用程序中只有一個實例,那麼也就說明了若是操做這一個對象,必然涉及到共享資源,涉及到資源分配問題,資源競爭等問題. 數據庫

那麼咱們的應用場景是什麼呢?設計模式

1. 網站的在線人數. 網站的在線人數在某一個時刻,全部人看到的是同樣的, 是這個網站這個時刻,全部用戶所共享的.安全

2. 池化技術. 好比數據庫的鏈接池. 每一個數據庫的可支持的鏈接數量是有限,並且鏈接對象建立和銷燬也是比較耗內存的. 經過一個統一的入口去控制,能夠保證對數據庫的壓力在可控的範圍內,同是也能夠保證出具庫鏈接的持續使用.併發

3. 配置中心. 一個應用程序針對經過一個配置文件的加載只須要加載一次便可,不須要屢次加載.網站

 

其實以上只是一些常見的應用場景,固然單例模式的應用場景也遠不止於此.this

本文參考的博客地址爲:http://www.javashuo.com/article/p-fcozwjup-gn.html線程

參考的博客的寫的很不錯, 若是想了解更多,能夠去看看這篇參考的博客設計

接下來咱們來看一下常見的實現方式,以及其中的對比.

 餓漢式,即直接初始化好,使用的時候直接調用便可.

package com.cbl.design.singletondesign;

public class HungrySingleton {
    private static final HungrySingleton singleton = new HungrySingleton();

    //限制外部產生HungrySingleton對象
    private HungrySingleton(){ }

    //向外提供獲取示例的靜態方法
    public static HungrySingleton getInstance() {
        return singleton;
    }


}

  

懶漢式, 顧名思義,就是懶,須要的時候再去初始化

package com.cbl.design.singletondesign;

public class LazySingleton {
    private static volatile LazySingleton singleton = null;

    private LazySingleton() { }

    public static LazySingleton getSingleton() {
        //不用每次獲取對象都強制加鎖,爲了提高了效率
        if (singleton == null) {
            synchronized (LazySingleton.class) {
                if (singleton == null) {
                    singleton = new LazySingleton();
                }
            }
        }
        return singleton;
    }
}

  

靜態內部類的方式

 

package com.cbl.design.singletondesign;

public class StaticInnerSingleton {
    /**
     * 類級的內部類,也就是靜態的成員式內部類,該內部類的實例與外部類的實例
     * 沒有綁定關係,並且只有被調用到時纔會裝載,從而實現了延遲加載。
     */
    private static class Singleton2Holder {
        /**
         * 靜態初始化器,由JVM來保證線程安全
         */
        private static StaticInnerSingleton singleton = new StaticInnerSingleton();
    }

    private StaticInnerSingleton() {
        //System.out.println("singleton2 private construct method called");
    }

    public static StaticInnerSingleton getSingleton() {
        //System.out.println("singleton2 getSingleton method called");
        return Singleton2Holder.singleton;
    }

    private String name;

    public void desc() {
        //System.out.println("singleton2 desc method called");
    }
}

  

還有一種實現方式是依賴於枚舉, 咱們知道枚舉中的對象是實例化好的,並且枚舉天生要求枚舉類的構造器必須私有,並且自己仍是被final 修飾的, 不可被繼承

package com.cbl.design.singletondesign;

public enum EnumSingleton {
    INSTANCE;

    public String getDesc() {
        return "desc";
    }

    public static void process() {
        System.out.println("static process method");
    }

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

  

以上是4中常見的構造單例模式的四種線程安全的構造單例的設計模式.網上可能還有其他的非線程安全的構建單例的方法, 可是線程安全的主要就是這四種.

(1) : 餓漢式 :  加載類的時候就會進行實例化,,若是後續沒有用到,則會搞成資源浪費.

(2) : 懶漢式 : 使用的時候再去初始化,這樣在前幾回調用併發調用的時候,會出現資源競爭, 等待時間較久,可是後續再次調用的時候, 因爲是雙重判斷加加鎖校驗機制, 不會出現阻塞.

(3): 靜態內部類 : 也是在使用的時候再去加載內部類並初始化外部類的對象,第一次調用會比較慢.

(4):枚舉單例:  類加載的時候就穿建立好對象了, 特色和餓漢式很像.

 

上面是這幾種單例方式的特色,其中懶漢式,餓漢式,靜態內部類的方式都不能防止反射,只有枚舉類能夠防止反射.

可是通常咱們的應用程序只須要保證能夠正常實現單例便可,不必過多的去防止單例模式,咱們使用單例模式,就是想構造單例對象的,可是咱們本身又去使用反射去破壞單例模式,這不是本身給本身找麻煩嗎.

相關文章
相關標籤/搜索