生活随笔
收集整理的這篇文章主要介紹了
【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 什么是代理模式
- 一. 代理模式簡介
- 二. 靜態代理模式
- 三. 動態代理模式
前言:筆記基于狂神設計模式視頻、《大話設計模式》觀后而寫
(最近一直在更新之前的刷題博客,今天久違地更新一篇新博客啦~)
什么是代理模式
一. 代理模式簡介
代理模式是很常用的設計模式噢~同時也有很多的類型,適當學習一下是非常有必要的!
- 定義:為其他對象提供一種代理,以控制對這個對象的訪問。
可以理解為:在訪問對象時引入一定程度的間接性,由這種間接性來附加多種用途。 - UML 圖:代理組合真實角色,代理和真實對色都繼承公共接口
- 舉個例子:經紀人(代理)、明星(真實角色),都繼承“接戲”接口。想找明星演戲的話,就得通過經紀人的“接戲”(把明星想象成經紀人的私有化對象)。這樣做的話,經紀人可以在自己的“接戲”方法上添加篩選、談薪等任務,而明星只需關注自己的業務即可。
- 在上面這個例子里,代理模式的好處就有體現出來了。真實角色更加地專一,并且在代理角色的拓展,也遵守了OOP原則的開放封閉原則。
- 代理模式的分類:
- 靜態代理
- 動態代理(這兩種類型,下文有結合代碼使用、講解)
- 遠程代理:為一個對象在不同地址空間提供局部代表,用于隱藏一個對象存在于不同地址空間的事實(比如調用另一臺PC的方法)
- 虛擬代理:用于存放實例化需要很長時間的真實對象,可以達到性能的最優化。比如打開嗶哩嗶哩,卡頓情況先顯示文字,而圖片、視頻流可能就只是一個白框之類的玩意,之后再逐漸加載出來,這里就用到了虛擬代理
- 安全代理、智能指引等其他分類,感興趣可以去查查~
二. 靜態代理模式
- 角色分類:
- 抽象角色:接口 or 抽象類。
- 真實角色:就被代理的角色
- 代理角色:真實角色的代理,一般會加一些附屬操作。
- 客戶:訪問代理角色的人。
- 好處:
- 使真實角色的操作更加純粹,不用關注一些公共的業務。
- 公共業務交給代理角色,實現了業務的分工
- 公共業務發生拓展的時候,方便管理
- 缺點:一個真實角色對應一個代理角色,代碼量增大,效率變低
- 樣例代碼:房東、中介、客戶、租房(試著想想對應上面的什么角色吧~)
public interface Rent {public void rent();
}
public class Host implements Rent{@Overridepublic void rent() {System.out
.println("房東:要出租房子");}
}
public class MyProxy implements Rent {private Host host
;MyProxy() {}MyProxy(Host host
) {this.host
= host
;}@Overridepublic void rent() {System.out
.println("中介:帶著看房");host
.rent();System.out
.println("中介:簽合同");}
}
public class Client {public static void main(String[] args
) {Host host
= new Host();MyProxy MyProxy = new MyProxy(host
);MyProxy.rent();}
}
三. 動態代理模式
為了解決上面靜態代理模式的缺點,這里又有了動態代理模式~
(這一塊不太好理解,我寫得估計也不太詳細,建議再看一下視頻、或者其他博客)
- 原理:動態代理基于反射機制實現。
- 和靜態代理的區別:
- 靜態代理:實現接口,再通過接口實現類的實例來代理。
- 動態代理:通過反射,造出一個接口類的實例。
(再原理一點,就是通過反射先造出一個帶構造方法的,接口的克隆體,再通過這個克隆體的構造方法,生成接口實例) - 使用到的類:
- Proxy:提供用于創建動態代理類和實例的靜態方法,生成一個
- InvocationHandler:每個代理實例都具有一個關聯的調用處理程序,調用代理實例的方法時,會被指派到其調用處理程序的 invoke 方法上。
- com.sun.proxy.$Proxy0 :由 Proxy::newProxyInstance() 生成的代理類。實現了傳入接口的每一個方法,以及Object方法。并且統一調用了InvocationHandler 的 invoke() 方法。
- 好處:
- 靜態代理的好處
- 一個動態代理類代理的是一個接口,一般就是對應的一類業務。規避了靜態代理的缺點
- 在原始類和接口未知時,就確定代理類的代理行為。靈活。
- 樣例代碼:還是房東中介的例子噢
public class ProxyInvocationHandler implements InvocationHandler {private Rent rent
;public void setRent(Rent rent
) {this.rent
= rent
;}public Object getMyProxy() {return Proxy.newProxyInstance(rent
.getClass().getClassLoader(), rent
.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object Proxy, Method method
, Object[] args
) throws Throwable {System.out
.println("動態代理來了噢!");Object res
= method
.invoke(rent
, args
);return res
;}
}public class Client {public static void main(String[] args
) {Host host
= new Host();ProxyInvocationHandler proxyInvocationHandler
= new ProxyInvocationHandler();proxyInvocationHandler
.setRent(host
);Rent proxy
= (Rent)proxyInvocationHandler
.getMyProxy();proxy
.rent();}
}
- 整理:無注釋,一個文件不到30行,寫完整個動態代理例子:
public interface Rent {void rent();
}public class RentDynamicProxy implements InvocationHandler {Rent rent
;RentDynamicProxy(Rent rent
) {this.rent
= rent
;}Object getProxy() {return Proxy.newProxyInstance(rent
.getClass().getClassLoader(), rent
.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy
, Method method
, Object[] args
) throws Throwable {System.out
.println("啟用動態代理");return method
.invoke(rent
, args
);}
}public class Host implements Rent{@Overridepublic void rent() {System.out
.println("房東出租");}public static void main(String[] args
) {Host host
= new Host();RentDynamicProxy rentDynamicProxy
= new RentDynamicProxy(host
);Rent proxy
= (Rent)rentDynamicProxy
.getProxy();proxy
.rent();}
}
萬能模版
public class BetterProxyInvocationHandler implements InvocationHandler {private Object target
;public void setTarget(Object target
) {this.target
= target
;}public Object getProxy() {return Proxy.newProxyInstance(target
.getClass().getClassLoader(), target
.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy
, Method method
, Object[] args
) throws Throwable {System.out
.println("執行了 " + method
.getName() + " 方法");Object res
= method
.invoke(target
, args
);return res
;}
}
總結
以上是生活随笔為你收集整理的【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。