《研磨設計模式》讀書筆記之:適配器模式、單例模式

前言:本篇系看完《研磨設計模式》一書的個人理解和總結,可能存在不正確的地方,看時需要持懷疑態度。另外,所有的圖都是示意圖,示意,示。

適配器模式(Adaptor):

幾點解釋:

  1. 本質:功能已經實現了,但是接口不匹配,中間加一層適配器類,通過轉調的方式,將已有的功能匹配到特定的接口上。
  2. 客戶端使用的是 接口A, 功能A,同時已經存在了功能B,只是接口和客戶端使用的 A接口不一致。此時,不想客戶端改動代碼,也不想改動功能B的實現代碼,那就需要在中間加一層 適配器類Adaptor,實現接口 A 並持有一個B的實例,Adaptor中的那些方法最終需要轉調 B實例的方法,從而 將B接口的功能適配到 A接口上。
  3. 適配適配,其實就是已有的東西不匹配,需要加個中間者來連接兩端。這其實在我們的生活中也會經常用到,電腦上各種的轉接線,就是現實生活中的硬件適配器。
  4. 有的時候,某些類庫可能很早就有了,後來又多了幾個類庫,幾個類庫給出了同一類型業務的不同處理,外觀差別很大,爲了我們可以以一種統一的方式使用這些類庫,我們可以定義或者以某個類庫的接口爲標準,將其他的類庫通過適配器的方式適配到同一個接口上,這樣統一了幾個類庫的外觀。當然,這種情況很少見,我們的前人在設計的時候很好的遵循了面向接口編程的思想,大多數時候都是先定義好接口,之後大家給出不同的實現。

單例模式(Singleton):

說明: 因爲在 JVM中通過 類加載器實例和類實例 來唯一確定一個 實例,即 Java中的單例是  類加載器級別的。

下面按照下列順序依次給出單例的Java實現:餓漢、懶漢、雙重檢查鎖、私有內部類、枚舉

餓漢模式:

public class Singleton {

    /**
     * 在 類加載的 init階段初始化,由JVM來保證只會初始化一次
     */
    private static Singleton singleton = new Singleton();

    /**
     * 構造方法私有 無法從外部創建實例
     */
    private Singleton(){
    }

    /**
     * 全局唯一訪問點
     * @return Singleton
     */
    public static Singleton getInstance(){
        return singleton;
    }
    
}

分析:在 類被加載時就已經完成了實例的初始化,而不是在 需要時,這點要注意

懶漢模式:

public class Singleton {
    
    private static Singleton singleton = null;

    /**
     * 構造方法私有 無法從外部創建實例
     */
    private Singleton(){
    }

    /**
     * 全局唯一訪問點 內置鎖同步,不然多線程下會 重複創建
     * @return Singleton
     */
    public static synchronized Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }

}

分析:做到了延遲加載,但是 不管實例有沒有被創建,每次都會有加鎖和解鎖的開銷,不合理,性能也不好

雙重檢查鎖(懶漢的優化):

public class Singleton {

    /**
     * 聲明爲 volatile
     * 不然多線程下,可能會出現線程獲取到的實例並未完全初始化
     */
    private static volatile Singleton singleton = null;

    /**
     * 構造方法私有 無法從外部創建實例
     */
    private Singleton(){
    }

    /**
     * 全局唯一訪問點
     * @return Singleton
     */
    public static  Singleton getInstance(){
        if (singleton == null){
            synchronized (Singleton.class){
                if (singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}

分析:延遲加載,有了實例的情況下不需要再進行 加鎖解鎖,但是 volatile 的使用還是會有輕微的性能問題,因爲每次都會直接操作主內存

私有內部類(比較優雅):

public class Singleton {

    /**
     * 構造方法私有
     */
    private Singleton(){
    }

    private static class SingletonHolder{
        private static Singleton singleton = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonHolder.singleton;
    }

}

分析:即利用了JVM的類初始化同步機制,又可以在 需要使用的時候才初始化,優雅。

枚舉(可能是更合適的單例實現方式):

public enum SingletonEnum {

    /**
     * 某單例
     */
    SOME_INSTANCE;

    private Singleton singleton;

    /**
     * 此方法由JVM在第一次使用枚舉類實例 的時候調用
     * 可以看成是 private 外部無法調用
     */
    SingletonEnum(){
        singleton = new Singleton();
    }

    public Singleton getInstance(){
        return this.singleton;
    }


    private class Singleton{
        private Singleton(){
        }

    }
}

分析:利用了 Java對枚舉的處理,更簡單

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