1.代理模式簡介
代理模式介紹
代理模式也叫委托模式译秦,是結(jié)構(gòu)型設(shè)計模式的一種。在現(xiàn)實生活中我們用到類似代理模式的場景有很多劣纲,比如代購逢捺、代理上網(wǎng)、打官司等癞季。
定義
為其他對象提供一種代理以控制這個對象的訪問劫瞳。
代理模式結(jié)構(gòu)圖
- Subject:抽象主題類,聲明真實主題與代理的共同接口方法绷柒。
- RealSubject:真實主題類志于,定義了代理所表示的真實對象,客戶端通過代理類間接的調(diào)用真實主題類的方法废睦。
- ProxySubject:代理類伺绽,持有對真實主題類的引用,在其所實現(xiàn)的接口方法中調(diào)用真實主題類中相應(yīng)的接口方法執(zhí)行。
- Client:客戶端類奈应,由它來調(diào)用代理類澜掩。
2.代理模式的簡單實現(xiàn)
假設(shè)我要買一個BV的包(博主我很喜歡一直買不起),國內(nèi)的太貴了杖挣,我找了個代購來幫我海外購買肩榕,這樣能省好多錢,哈哈程梦。
抽象主題類(Subject)
抽象主題類具有真實主題類和代理的共同接口方法点把,我想要代購,那共同的方法就是購買:
public interface IShop {
//購買
void buy();
}
真實主題類(RealSubject)
這個購買者LiuWangShu也就是我屿附,實現(xiàn)了IShop接口提供的 buy()方法:
public class LiuWangShu implements IShop {
@Override
public void buy() {
System.out.println("購買");
}
}
代理類(ProxySubject)
我找的代理類同樣也要實現(xiàn)IShop接口郎逃,并且要持有被代理者,在buy()方法中調(diào)用了被代理者的buy()方法:
public class Purchasing implements IShop {
private IShop mShop;
public Purchasing(IShop shop){
mShop=shop;
}
@Override
public void buy() {
mShop.buy();
}
}
客戶端類(Client)
public class Client {
public static void main(String[] args){
//創(chuàng)建LiuWangShu
IShop liuwangshu=new LiuWangShu();
//創(chuàng)建代購者并將LiuWangShu作為構(gòu)造函數(shù)傳
IShop purchasing=new Purchasing(liuwangshu);
purchasing.buy();
}
}
看完客戶端類的代碼挺份,其實也是很好理解褒翰,就是代理類包含了真實主題類(被代理者),最終調(diào)用的都是真實主題類(被代理者)實現(xiàn)的方法匀泊,在上面的例子就是LiuWangShu類的buy()方法优训,所以運行的結(jié)果就是“購買”。
3.動態(tài)代理的簡單實現(xiàn)
從編碼的角度來說各聘,代理模式分為靜態(tài)代理和動態(tài)代理揣非,上面的例子是靜態(tài)代理,在代碼運行前就已經(jīng)存在了代理類的class編譯文件躲因,而動態(tài)代理則是在代碼運行時通過反射來動態(tài)的生成代理類的對象早敬,并確定到底來代理誰。也就是我們在編碼階段不需要知道代理誰大脉,代理誰我們將會在代碼運行時決定搞监。Java提供了動態(tài)的代理接口InvocationHandler,實現(xiàn)該接口需要重寫invoke()方法镰矿。下面我們在上面靜態(tài)代理的例子上做修改:
創(chuàng)建動態(tài)代理類:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicPurchasing implements InvocationHandler{
private Object obj;
public DynamicPurchasing(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=method.invoke(obj, args);
return result;
}
}
在動態(tài)代理類中我們聲明一個Object的引用琐驴,該引用指向被代理類,我們調(diào)用被代理類的具體方法在invoke()方法中執(zhí)行秤标。接下來我們修改客戶端類代碼:
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args){
//創(chuàng)建LiuWangShu
IShop liuwangshu=new LiuWangShu();
//創(chuàng)建動態(tài)代理
DynamicPurchasing mDynamicPurchasing=new DynamicPurchasing(liuwangshu);
//創(chuàng)建LiuWangShu的ClassLoader
ClassLoader loader=liuwangshu.getClass().getClassLoader();
//動態(tài)創(chuàng)建代理類
IShop purchasing= (IShop) Proxy.newProxyInstance(loader,new Class[]{IShop.class},mDynamicPurchasing);
purchasing.buy();
}
}
4.代理模式的應(yīng)用
代理模式類型
代理模式的類型主要有以下幾點:
- 遠程代理:為一個對象在不同的地址空間提供局部代表绝淡,這樣系統(tǒng)可以將Server部分的事項隱藏。
- 虛擬代理:使用一個代理對象表示一個十分耗資源的對象并在真正需要時才創(chuàng)建苍姜。
- 安全代理:用來控制真實對象訪問時的權(quán)限够委。
- 智能指引:當(dāng)調(diào)用真實的對象時,代理處理另外一些事怖现,比如計算真實對象的引用計數(shù)茁帽,當(dāng)該對象沒有引用時玉罐,可以自動釋放它;或者訪問一個實際對象時潘拨,檢查是否已經(jīng)能夠鎖定它吊输,以確保其他對象不能改變它。
代理模式使用場景
無法或者不想直接訪問某個對象時可以通過一個代理對象來間接的訪問铁追。