字節(jié)跳動飛書內(nèi)推!
北京包个、杭州刷允、武漢、廣州碧囊、深圳树灶、上海,六大城市等你來投糯而。
感興趣的朋友可以私我咨詢&內(nèi)推天通,也可以通過鏈接直接投遞!
海量HC熄驼,極速響應(yīng)像寒,快來和我成為同事吧。
今日頭條瓜贾、抖音诺祸、Tik Tok也可以內(nèi)推~
點擊進入我的博客
代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象對引用祭芦。
3.5.1 代理模式結(jié)構(gòu)
- 抽象主題(Subject)角色:聲明了真實主題和代理主題的共同接口
- 代理主題(Proxy)角色:代理主題角色內(nèi)部含有對真實主題的引用筷笨,從而可以在任何時候操作真實主題對象;代理主題角色提供一個與真實主題角色相同的接口龟劲,以便可以在任何時候都可以替代真實主題控制對真實主題的引用胃夏,負責(zé)在需要的時候創(chuàng)建真實主題對象(和刪除真實主題對象);代理角色通常在將客戶端調(diào)用傳遞給真實的主題之前或之后昌跌,都要執(zhí)行某個操作仰禀,而不是單純地將調(diào)用傳遞給真實主題對象。
- 真實主題(RealSubject)角色:定義了代理角色所代表的真實對象蚕愤。
public class Test {
public static void main(String[] args) {
Subject subject = new RealSubject();
Subject proxy = new ProxySubject(subject);
proxy.request(); // 此處通過代理類來執(zhí)行
}
}
interface Subject {
void request();
}
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject");
}
}
class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
System.out.println("ProxySubject");
}
}
3.5.2 動態(tài)代理
自從JDK 1.3以后悼瘾,Java在java.lang.reflect
庫中提供了一下三個類直接支持代理模式:Proxy
、InvocationHander
审胸、Method
亥宿。
動態(tài)代理步驟
- 創(chuàng)建一個真實對象
- 創(chuàng)建一個與真實對象有關(guān)的調(diào)用處理器對象
InvocationHandler
- 創(chuàng)建代理,把調(diào)用處理器和要代理的類聯(lián)系起來
Proxy.newInstance()
- 在調(diào)用處理對象的
invoke()
方法中執(zhí)行相應(yīng)操作
public class Test {
public static void main(String[] args) {
// 創(chuàng)建要被代理的實例對象
Subject subject = new RealSubject();
// 創(chuàng)建一個與被代理實例對象有關(guān)的InvocationHandler
InvocationHandler handler = new ProxySubject(subject);
// 創(chuàng)建一個代理對象來代理subject砂沛,被代理的對象subject的每個方法執(zhí)行都會調(diào)用代理對象proxySubject的invoke方法
Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[]{Subject.class}, handler);
// 代理對象執(zhí)行
proxySubject.request();
}
}
interface Subject {
void request();
}
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject");
}
}
class ProxySubject implements InvocationHandler {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
/**
* @param proxy 要代理的
* @param method
* @param args
* @return
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before Proxy");
Object obj = method.invoke(subject, args);
System.out.println("After Proxy");
return obj;
}
}
- 可以使用范型來創(chuàng)建
ProxySubject
- 可以使用匿名內(nèi)部類減少代碼數(shù)量請查看14.7節(jié)
3.5.3 細節(jié)
優(yōu)點
- 代理類和真實類分離烫扼,職責(zé)清晰。
- 在不改變真是累代碼的基礎(chǔ)上擴展了功能碍庵。
缺點
- 由于在客戶端和真實主題之間增加了代理對象映企,因此有些類型的代理模式可能會造成請求的處理速度變慢悟狱。
- 實現(xiàn)代理模式需要額外的工作,有些代理模式的實現(xiàn)非常復(fù)雜堰氓。
和適配器模式的關(guān)系
適配器模式的用意是改變所考慮對象的接口挤渐,而代理模式不能改變。
和裝飾模式
- 裝飾模式應(yīng)當(dāng)為所裝飾的對象提供增強功能
- 代理模式對對象的使用施加控制双絮,并不提供對象本身的增強功能
虛擬代理
- 虛擬代理模式(Virtual PRoxy)會推遲真正所需對象實例化時間浴麻。在需要真正的對象工作之前,如果代理對象能夠處理囤攀,那么暫時不需要真正對象來出手软免。
- 當(dāng)一個真實主題對象的加載需要耗費資源時,一個虛擬代理對象可以代替真實對象接受請求焚挠,并展示“正在加載”的信息膏萧,并在適當(dāng)?shù)臅r候加載真實主題對象。