前言:本篇系看完《研磨設計模式》一書的個人理解和總結,可能存在不正確的地方,看時需要持懷疑態度。另外,所有的圖都是示意圖,示意,示。
適配器模式(Adaptor):
幾點解釋:
- 本質:功能已經實現了,但是接口不匹配,中間加一層適配器類,通過轉調的方式,將已有的功能匹配到特定的接口上。
- 客戶端使用的是 接口A, 功能A,同時已經存在了功能B,只是接口和客戶端使用的 A接口不一致。此時,不想客戶端改動代碼,也不想改動功能B的實現代碼,那就需要在中間加一層 適配器類Adaptor,實現接口 A 並持有一個B的實例,Adaptor中的那些方法最終需要轉調 B實例的方法,從而 將B接口的功能適配到 A接口上。
- 適配適配,其實就是已有的東西不匹配,需要加個中間者來連接兩端。這其實在我們的生活中也會經常用到,電腦上各種的轉接線,就是現實生活中的硬件適配器。
- 有的時候,某些類庫可能很早就有了,後來又多了幾個類庫,幾個類庫給出了同一類型業務的不同處理,外觀差別很大,爲了我們可以以一種統一的方式使用這些類庫,我們可以定義或者以某個類庫的接口爲標準,將其他的類庫通過適配器的方式適配到同一個接口上,這樣統一了幾個類庫的外觀。當然,這種情況很少見,我們的前人在設計的時候很好的遵循了面向接口編程的思想,大多數時候都是先定義好接口,之後大家給出不同的實現。
單例模式(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對枚舉的處理,更簡單