創建型之設計模式

簡述

設計模式類型有3種(創建型,結構型,行爲型)
以下逐一列出創建型類型的設計模式:
1單例,2原型,3工廠,4抽象工廠,5構建者(創建者)模式。

一、單例模式

單例模式就是在一個jvm中只能創建一個對象;分餓漢式單例模式和懶漢式單例模式。

  • 餓漢式是加載類的時候就創建該對象。
  • 懶漢式爲用的時候才創建該對象。

適用場景

spring中bean的創建默認單例模式
應用服務器有很多系統參數在服務運行期間不會改變的,可用單例創建。

餓漢式demo

  • 餓漢式單例模式,類加載的時候就實例化對象,線程安全。
  • 簡單實用,推薦
  • 個人認爲 不算嚴重的一個缺點,不管用到與否,類裝載時就完成實例化
/**餓漢式   線程安全,加載類時就創建對象*/
public class Mgr01 {
    private static final Mgr01 INSTANCE=new Mgr01();//2 私有靜態化常量來創建對象
    private Mgr01(){};//1私有化構造方法

    public static Mgr01 getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) {
        Mgr01 m1=Mgr01.getInstance();
        Mgr01 m2=Mgr01.getInstance();
        System.out.println(m1==m2);
    }
}

懶漢式demo

demo1 方法,效率低下,不推薦

  • 解決按需初始化,線程安全
  • 特點:在方法上加同步代碼塊,效率低
 public class Mgr04 {
    private static Mgr04 INSTANCE;

    private Mgr04(){
        }
        public static synchronized  Mgr04 getInstance(){  //synchronized 鎖定當前對象,加了static  鎖定的是class對象
            if(INSTANCE==null){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                INSTANCE=new Mgr04();
            }
            return INSTANCE;

        }

    public static void main(String[] args) {
        for (int i=0;i<100;i++){
            new Thread(()-> System.out.println(getInstance().hashCode())).start();
        }
    }
}

以下爲3種較好的懶漢式單例實現demo,用到時才實例化

2 雙重檢查,即在同步塊前後分別加實例判空邏輯

  • spring容器中註冊bean的獲取,就是採用雙重檢查懶加載的單例模式;
  • 傳統懶漢式單例中,被認爲是最好的懶漢式單例**<後面還有兩個不錯的單例>**
/**懶漢式
 * 滿足按需初始化,滿足線程安全
 * 較好1
 * */
public class Mgr06 {
    private static volatile Mgr06 INSTANCE;//JIT
    private Mgr06(){}

    public static Mgr06 getInstance(){
        if(null==INSTANCE){
            synchronized (Mgr06.class){
                if(null==INSTANCE){//雙重檢查
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE=new Mgr06();
                }
            }

        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for(int i=1;i<100;i++){
            new Thread(()-> System.out.println(getInstance().hashCode())).start();
        }
    }
}

3 運用虛擬機類加載知識,懶漢式:靜態內部類方式

  • 滿足按需初始化,且線程安全
  • jvm保證單例,加載外部類時不加載私有靜態內部類,可以實現懶加載
 public class Mgr07 {
    private Mgr07(){}

    private static class Mgr07Holder {
        private static final Mgr07 INSTANCE=new Mgr07();
    }

    public static Mgr07 getInstance(){
        return Mgr07Holder.INSTANCE;
    }

    public static void main(String[] args) {
        new Thread(()-> System.out.println(getInstance().hashCode())).start();
    }
}

4 解決線程同步,且能防止反序列化(因爲枚舉類沒有構造方法)

  • 源自effective java 是java原作者寫的一本書
  • 最優單例,可防止反序列化,線程安全
  • 餓漢式單例
public enum  Mgr08 {
    INSTANCE;

    public static void main(String[] args) {
            for (int i=1;i<100;i++){
                new Thread(()-> System.out.println(Mgr08.INSTANCE.hashCode())).start();
            }
        }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章