隨筆記:設(shè)計模式一代理模式
感謝:https://juejin.im/post/5d7c6bc7f265da03f3338254
介紹
代理模式 (Proxy Pattren) 也稱為委托模式蒿柳,是屬于結(jié)構(gòu)型設(shè)計模式,其重要性不言而喻,相信在看過本篇文章之后會發(fā)現(xiàn)不少設(shè)計模式中都有代理模式的影子佛寿。那么何為代理模式串前?其實(shí)代理在我們?nèi)粘I钪胁⒉簧僖娚⒊常瑢τ诔绦騿T來說最常接觸的莫過于代理上網(wǎng)了十籍,連上代理服務(wù)器地址见剩,就可以輕松暢游全世界的網(wǎng)絡(luò)蓬衡;總而言之喻杈,也許你并不留意,但是代理是無處不在狰晚,現(xiàn)實(shí)生活如此筒饰,我們的 Code 世界里也是如此!既然這樣壁晒,我們來探究下代理模式倒是有多普遍瓷们。下面首先看下代理模式的定義吧。
定義
為其它對象提供一種代理以控制對這個對象的訪問秒咐。
使用場景
當(dāng)無法或不想直接訪問某個對象存在困難時可以通過一個代理對象來間接訪問谬晕,為了保證客戶端使用的透明性,委托對象與代理對象需要實(shí)現(xiàn)相同的接口携取。
UML 類圖
- Subject: 抽象主題類攒钳;該類的主要職責(zé)是聲明真實(shí)主題與代理的共同接口方法,該類既可以是一個抽象類也可以是一個接口雷滋。
- RealSubject: 真實(shí)主題類不撑;該類也稱為被委托類或被代理類,該類定義了代理所表示的真實(shí)對象晤斩,由其執(zhí)行具體的業(yè)務(wù)邏輯方法焕檬,而客戶類則通過代理類間接地調(diào)用真實(shí)主題中定義的方法。
- ProxySubject: 代理類澳泵;該類也稱為委托類或代理類实愚,該類持有一個對真實(shí)主題類的引用,在其所實(shí)現(xiàn)的接口方法中調(diào)用真實(shí)主題類中相應(yīng)的接口方法執(zhí)行,以此起到代理的作用爆侣。
- Client: 客戶類萍程,即使用代理類的類型。
代碼示例
代理模式可以大致分為兩大部分兔仰,一是靜態(tài)代理茫负,而是動態(tài)代理。靜態(tài)代理是只有具體的代理對象乎赴,而動態(tài)代理則與靜態(tài)代理相反忍法,通過反射機(jī)制動態(tài)地生成代理者的對象,也就是說我們在 code 階段壓根不需要知道代理對象是誰榕吼,代理誰將會在執(zhí)行階段決定饿序。下面我們就來看下吧
簡單示例
靜態(tài)代理
業(yè)務(wù)背景: X 程序員在公司上班時,遇見了公司拖欠工資甚至克扣工資的情況羹蚣,這種情況下 X 程序員還是通過法律途徑來解決問題原探,這個時候就需要請一個律師來作為自己的訴訟代理人,先看下面的代碼示例吧
訴訟接口類:
public interface ILawsuit {
/**
* 提交申請
*/
void submit();
/**
* 舉行舉證
*/
void burden();
/**
* 開始辯護(hù)
*/
void defend();
/**
* 訴訟完成
*/
void finish();
}
復(fù)制代碼
具體訴訟人(X程序員):
public class XProgrammer implements ILawsuit {
@Override
public void submit() {
System.out.println("老板欠 X 程序員工資顽素,申請仲裁!");
}
@Override
public void burden() {
System.out.println("這是合同書和過去一年的銀行工資流水");
}
@Override
public void defend() {
System.out.println("證據(jù)確鑿咽弦!不需要再說什么了!");
}
@Override
public void finish() {
System.out.println("訴訟成功胁出!判決老板即日起 7 天內(nèi)結(jié)算工資型型!");
}
}
復(fù)制代碼
X程序員請的律師(代理對象):
public class ProxyLawyer implements ILawsuit {
/**
* 持有一個具體被代理者的引用,這里就是 X 程序員全蝶,也可以是其它 Y 程序員 只是具體說明闹蒜。
*/
private ILawsuit mLawsuit;
public ProxyLawyer(ILawsuit lawsuit) {
mLawsuit = lawsuit;
}
@Override
public void submit() {
mLawsuit.submit();
}
@Override
public void burden() {
mLawsuit.burden();
}
@Override
public void defend() {
mLawsuit.defend();
}
@Override
public void finish() {
mLawsuit.finish();
}
}
復(fù)制代碼
test:
@Test
public void testProxy(){
//X 程序員
ILawsuit lawsuit = new XProgrammer();
//程序員請的律師,把自己的事務(wù)交于律師來處理
ILawsuit proxyLawyer = new ProxyLawyer(lawsuit);
//律師開始處理
proxyLawyer.submit();
proxyLawyer.burden();
proxyLawyer.defend();
proxyLawyer.finish();
}
復(fù)制代碼
output:
老板欠 X 程序員工資抑淫,申請仲裁!
這是合同書和過去一年的銀行工資流水
證據(jù)確鑿绷落!不需要再說什么了!
訴訟成功丈冬!判決老板即日起 7 天內(nèi)結(jié)算工資嘱函!
復(fù)制代碼
動態(tài)代理
動態(tài)代理其實(shí)也很簡單,Java 給我們提供了一個很便捷的動態(tài)代理接口 InvocationHandler ,實(shí)現(xiàn)該接口需要重寫其調(diào)用方法 invoke埂蕊。
下面我們就上面的示例來稍加改動一下:
動態(tài)代理類(這里可以理解為律師對象)
public class DynamicProxy implements InvocationHandler {
/**
* 代理者的引用(這里可以理解為 X 程序員)
*/
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通過反射調(diào)用其代理者的方法
return method.invoke(object,args);
}
}
復(fù)制代碼
test:
@Test
public void testDynamicProxy(){
//X 程序員
ILawsuit lawsuit = new XProgrammer();
//構(gòu)造一個動態(tài)代理對象(程序員請的律師往弓,把自己的事務(wù)交于律師來處理)
DynamicProxy dynamicProxy = new DynamicProxy(lawsuit);
//拿到代理者身上的 ClassLoader
ClassLoader classLoader = lawsuit.getClass().getClassLoader();
//動態(tài)的構(gòu)造一個代理者律師出來
ILawsuit proxyLawyer = (ILawsuit) Proxy.newProxyInstance(classLoader, new Class[]{ILawsuit.class}, dynamicProxy);
//律師開始處理
proxyLawyer.submit();
proxyLawyer.burden();
proxyLawyer.defend();
proxyLawyer.finish();
}
復(fù)制代碼
output:
老板欠 X 程序員工資,申請仲裁!
這是合同書和過去一年的銀行工資流水
證據(jù)確鑿蓄氧!不需要再說什么了函似!
訴訟成功!判決老板即日起 7 天內(nèi)結(jié)算工資喉童!
復(fù)制代碼
運(yùn)行結(jié)果和靜態(tài)代理一樣撇寞,由此可見動態(tài)代理通過一個代理類來代理 N 多個被代理類,其本質(zhì)是對代理者與被代理者進(jìn)行解耦,使兩者沒有直接的耦合關(guān)系蔑担。相對而言靜態(tài)代理則是能為給定接口下的實(shí)現(xiàn)類做代理牌废,如果接口不同那么就需要重新定義不同的代理類,最為復(fù)雜啤握,但是靜態(tài)代理更符合面向?qū)ο笤瓌t鸟缕。在開發(fā)時具體使用哪種方式來實(shí)現(xiàn)代理,就看自己的偏好了排抬。
總結(jié)
代理模式應(yīng)用廣泛懂从,在后面的結(jié)構(gòu)型模式中,你都可以看到代理模式的影子蹲蒲,有些模式單獨(dú)作為一種設(shè)計模式番甩,倒不如說是對代理模式的一種針對性優(yōu)化。而且代理模式幾乎沒有缺點(diǎn)可言届搁,它是細(xì)分化至很小的一種模式缘薛,如果非得說一個缺點(diǎn)的話,那么就是設(shè)計模式的通病卡睦,對類的增加掩宜。不過在這種孰優(yōu)孰劣的局勢下,就算對類的稍微增加又有什么問題呢么翰,是吧?
作者:DevYK
鏈接:https://juejin.im/post/5d7c6bc7f265da03f3338254
來源:掘金
著作權(quán)歸作者所有辽旋。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)浩嫌,非商業(yè)轉(zhuǎn)載請注明出處。