外觀(門面)模式 化零為整,把零碎的功能拼成一個整體,對外提供一個統一介面,用來訪問子系統中的多個介面。 總結 解耦,不需要一個個對接,使用簡單。 單例模式 負責創建對象,同時確保只有單個對象被創建。 餓漢式 線程安全,在類載入時就會進行初始化,訪問時直接使用。 public class Stude ...
外觀(門面)模式
化零為整,把零碎的功能拼成一個整體,對外提供一個統一介面,用來訪問子系統中的多個介面。
總結
解耦,不需要一個個對接,使用簡單。
單例模式
負責創建對象,同時確保只有單個對象被創建。
餓漢式
線程安全,在類載入時就會進行初始化,訪問時直接使用。
public class Student { private static final Student student = new Student(); private Student() {} public static Student getInstance() { return student; } }
在類載入的時候便完成了實例化。
飽漢(懶漢)式
需要使用時才會去創建實例。
public class Student { private volatile static Student student; private Student() {} public static Student getInstance() { if (student == null) { synchronized (Student.class) { if (student == null) { student = new Student(); } } } return SINGLETON; } }
如果要保證線程安全,需要添加雙重鎖,當兩個線程同時執行 getInstance 時,結果都為 true,會導致一起進入排隊狀態,從而重覆創建新的對象;
所以需要雙重判斷,預防多線程重覆創建。
靜態內部類
public class Student { private Student() {} private static class Instance { private static final Student student = new Student(); } public static Student getInstance() { return Instance.student; } }
線程安全,只有使用時才會創建實例,不會造成資源浪費的問題。
枚舉式
public class Student { private enum StudentEnum { INSTANCE; private final Student instance; StudentEnum() { instance = new Student(); } private Student getInstance() { return instance; } } private Student() {} public static Student getInstance() { return StudentEnum.INSTANCE.getInstance(); } }
線程安全,只會裝載一次,無論是序列化、反序列化、反射還是克隆都不會新創建對象。
簡單工廠 & 抽象工廠
工廠模式將對象的創建和使用分離,屬於一個產品系列,而抽象工廠是多個產品系列一個工廠類。
//寶馬系列
BMWCar bmBean = CarFactory.create(Car.BMW); BMWX1 x1 = bmBean.getX1();
x1.drive();
BMWZ4 z4 = bmBean.getZ4();
z4.drive();
//賓士系列 BenZCar benZBean = CarFactory.create(Car.BenZ);
BenZSUV suvBean = benZBean.getSUV(); suvBean.speed(); suvBean.stop();
總結
解耦,提高擴展,但是每次新增需要修改原代碼。
構鍵者模式
用於一步步創建複雜對象,一般分產品類,構鍵類和組裝類,通常用於配置工具類使用。
代理模式
為兩者之間提供一個代理對象(攔截層),並且目標對象只能被代理對象訪問,調用目標對象都要先通過代理對象。
靜態代理
目標對象和代理對象實現共同的介面或繼承相同的父類,在不修改目標對象的前提下進行擴展。
平時接手代碼,就可以在不修改原代碼的基礎上擴展原有功能。
總結
代理對象需要與目標對象實現一樣的介面,一對一模式,會導致代理類比較多;
介面修改後,目標對象與代理對象都要修改,維護成本高,適合目標類比較少的情況。
動態代理
一對多模式,一個代理類可利用反射機制代理多個委托類,並且是在運行時創建動態代理類。
JDK介面動態代理
代理對象不需要實現介面,目標對象必須實現介面。
Proxy.newProxyInstance(classLoader 類載入器, classInterfaces[] 介面列表, InvocationHandler 攔截處理類
);
總結
可以將代理類的創建推遲到運行時期,代理類通過 JDK 的 API 動態在記憶體中創建,這樣就可以大大減少代理類的創建和維護,但前提是目標類必須實現介面。
Cglib子類動態代理
不強制實現介面,在記憶體中動態的創建一個目標類的子類對象,從而實現對目標類的代理。
總結
通過 ASM 框架轉換位元組碼並生成新類,不能使用 final 修飾代理方法。
可以直接生成二進位 class 文件,也可以在類被載入到 Java 虛擬機之前改變類行為。
責任鏈模式
請求在鏈上一個個傳遞,直到鏈中某個對象處理。
總結
可以控制請求順序,新增不用修改原代碼,邏輯解耦,單一職責,效率不高,比較複雜,符合多個認證或者校驗等場景。
享元模式
共用基本的單元、元件,提升已有元件的復用率,減少重覆製造開銷。
代碼中主要分元件跟工廠類,工廠中編寫獲取方法,方法判斷該元件是否存在,如果不存在新建元件,存入共用池中,如果存在直接從池中獲取返回,類似單例。
總結
減少了資源的使用,但是增加了代碼的複雜程度。