一文了解代理設計模式下的,靜態代理與動態代理的區別。
前言:
開發了多年,看了不少原始碼,發現許多原始碼涉及到設計模式很多,比如常見的單例、工廠以及建造者模式等等。今天為大家介紹下代理設計模式,靜態代理與動態代理的區別所在,以及業務場景。
代理模式又稱為委託模式,主要分為
- 靜態代理
- 動態代理
代理模式的設計裡面是限制對物件的直接訪問,要想訪問具體物件需要通過該物件的代理類去訪問。
靜態代理
靜態代理主要分為下面三個部分:
- 抽象介面 ISubject
- 具體物件 RealSubject
- 代理物件 ProxySubject
舉個生活中我們使用第三方支付的例子
建立購物抽象類:IPay
public interface IPay{ void pay(); }
建立具體實際的第三方支付抽象類:(比如微信支付)
public class WechatPay implements IPay {
@Override
public void pay() {
System.out.println("執行了微信支付功能");
}
}
建立代理類:
public class ProxyPay implements IPay { /** * 實際上支付的物件 */ private IPay ipay; public ProxyShop(IPay ipay) { this.ipay= ipay; } @Override public void pay() { System.out.println("使用APP微信支付"); ipay.pay(); System.out.println("微信已支付,等待後端回撥結果"); } }
建立測試類:
public class Main {
public static void main(String[] args) {
WechatPay wechatPay= new WechatPay ();
ProxyPay proxyPay = new ProxyPay (wechatPay);
proxyPay.pay();
}
}
結果
可以看到,微信支付 幫我們完成了支付操作,並且在代理類過程中,可以增加一些特殊的操作,在支付操作的前後可以增加自定義操作。
動態代理
上面講了靜態代理,我們需要預先把需要的情況都要列出來,然後編寫代理程式碼,需要自己生成編寫代理類。
而動態代理就可以在執行時通過 Proxy.newProxyInstance生成代理類,比如我們有了新的需求,讓朋友幫我們交話費,這個時候,就需要建立交話費的抽象,然後建立充話費的代理,這是很麻煩的,下面通過動態代理模式實現。
下面仍然以購物為例
抽象支付:
public interface IPay{
void pay();
}
實際代理物件:WechatPay
public class WechatPay implements IPay {
@Override
public void pay() {
System.out.println("執行了微信支付功能");
}
}
動態代理:
public class DynamicProxyHandler implements InvocationHandler {
Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用APP微信支付");
method.invoke(target,args);
System.out.println("微信已支付,等待後端回撥結果");
return null;
}
}
測試類:
public class Main {
public static void main(String[] args) {
WechatPay wechatPay= new WechatPay ();
DynamicProxyHandler dynamicProxyHandler = new DynamicProxyHandler(wechatPay);
IPay ipay= (IPay ) Proxy.newProxyInstance(WechatPay .class.getClassLoader(),WechatPay .class.getInterfaces(),dynamicProxyHandler);
ipay.pay();
}
}
結果輸出如上圖一樣。
總結:可以看到,我們可以在方法具體執行的前後加入一些自定義邏輯,更加靈活,而且在沒修改原來方法的情況下,可以增強程式碼功能。
通過上面的例項可以發現:
靜態代理的代理類需要自己編寫,而動態代理的代理類則是由執行時使用 newProxyInstance 動態生成,
同時不管是靜態代理還是動態代理,都需要實現介面,本質上是面對介面程式設計的,能夠增加現有程式碼的功能。
區別 :
靜態代理
靜態代理業務類只需要關注業務邏輯本身,保證了業務類的重用性。代理物件的一個介面只服務於一種型別的物件,如果要代理的方法很多,需要為每一種方法都進行代理,靜態代理在程式規模稍大時就無法勝任。如果介面增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法,增加了程式碼維護的複雜度。
動態代理
動態代理與靜態代理相比較,最大的好處是介面中宣告的所有方法都被轉移到呼叫處理器一個集中的方法中處理(InvocationHandler invoke)。這樣,在介面方法數量比較多的時候,可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。而且動態代理的應用使類職責更加單一,複用性更強。