代理模式、配接器模式與裝飾器模式
這三種設計模式在代碼形式上十分相似,但是為了解決不同的問題而提出的:
- 代理模式
- 代理模式在不改變原始介面的條件下,為原始類控制訪問、新增一些業務無關的功能,
- 配接器模式
- 將不兼容的介面轉換為可兼容的介面,(一種以修正為目的的設計模式),
- 裝飾器模式
- 裝飾器模式是對原始類的功能進行增強,支持多個裝飾類的嵌套增強,
代理模式
?? 代理模式主要有兩種實作,一種是靜態代理,需要與被代理類實作相同的介面,也可以使用java提供的反射機制,進行靈活的動態代理靜態代理
- 基于介面,若被代理類有介面,那么通常我們的代理類會實作與之一樣的介面,注入被代理類,并在實作時,對被代理類進行增強,
- 基于繼承,有些被代理類并沒有介面,因此只能使用繼承的方式進行擴展,
動態代理
靜態代理的問題: 當我們有非常多實作了不同介面的類需要被代理的時候,靜態代理的方式就顯得非常麻煩,我們需要給每個被代理類實作相同的代理邏輯,但代碼大多數都是重復的,我們可以使用反射進行動態代理來解決這一問題,
動態代理Java實作
我們需要實作InvocationHandler 介面,
private class DynamicProxyHandler implements InvocationHandler {
private Object proxiedObject;
public DynamicProxyHandler(Object proxiedObject) {
this.proxiedObject = proxiedObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Th
long startTimestamp = System.currentTimeMillis();
Object result = method.invoke(proxiedObject, args);
long endTimeStamp = System.currentTimeMillis();
long responseTime = endTimeStamp - startTimestamp;
String apiName = proxiedObject.getClass().getName() + ":" + method.getNam
RequestInfo requestInfo = new RequestInfo(apiName, responseTime, startTim
metricsCollector.recordRequest(requestInfo);
return result;
}
}
實作完成后,將這個實作,以及被代理類的類加載器、被代理類的介面一同傳入Proxy類的靜態方法newProxyinstance中,就可以動態的創建代理類了,
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
代理模式的應用
- 非業務邏輯的剝離
- 對于日志、快取讀寫、性能統計等非業務邏輯相關的代碼,可以使用統一的代理類進行管理,
- RPC框架消費者呼叫時
- RPC呼叫時,作為消費方,之所以能像呼叫本地方法一樣呼叫服務端的遠程方法,是因為這里使用代理模式為我們屏蔽了服務提供方尋址、請求序列化、結果反序列化等程序,
配接器模式
?? 配接器模式可以基于類實作,也可以基于物件實作,基于類實作使用繼承的方式進行實作,而基于物件則是用組合的形式實作,基于類
簡單來說,就是定義一個配接器介面,并繼承需要被適配的類,然后實作配接器介面的相應方法,在實作介面的方法時,我們只需要實作那些需要被改造的舊介面,對于符合要求的舊介面,可以繼續沿用父類方法,(因此,如果需要適配的物件介面很多,并且和新介面定義大部分都相同,那么可以直接使用基于類的實作)
基于實作
基于實作的方法,是將被適配的類注入進來,再進行相應改造的方式,相較基于類的方式,更靈活,如果新舊介面存在較多的不一致,推薦使用基于實作的方式,會更加靈活,
使用場景
- 封裝舊系統的api
- 方法名稱語意不清晰?
- 引數過多?
- 性能過低?
- 替換外部依賴
- 兼容老版本
實際應用
比如slf4j就是一套統一不同底層日志包的介面,此外,考慮到不同日志包的api存在的不同,slf4j還提供了相應的配接器,來統一api管理,
裝飾器模式
?? 裝飾器模式一般使用基于實體的方式,具有更好的擴展性,但同時,裝飾器模式一般還會繼承與原始類相同的父類,可以達到嵌套增強的目的,轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/503619.html
標籤:其他
