歸功于偉大的長(zhǎng)城桨踪,我們幾乎每個(gè)上網(wǎng)的人都知道了代理的概念瑞信,那么省去繁雜的應(yīng)用場(chǎng)景顷帖,今天就來(lái)總結(jié)一下代理模式以及運(yùn)用逆航。
代理模式
為其他對(duì)象提供一個(gè)代理鼎文,以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。
那么有人會(huì)問(wèn)了因俐,為什么不直接訪問(wèn)澳赐铩?老鐵抹剩,點(diǎn)擊這個(gè)網(wǎng)址你就知道了撑帖。
簡(jiǎn)單的使用
首先為了訪問(wèn)真實(shí)對(duì)象,我們需要先創(chuàng)造一個(gè)接口澳眷,讓真實(shí)對(duì)象與代理對(duì)象都實(shí)現(xiàn)接口胡嘿,才能在使用時(shí)方便的進(jìn)行轉(zhuǎn)型。
- 接口主題
public interface Subject {
void visit();
}
接下來(lái)我們模擬一個(gè)真實(shí)對(duì)象的類,并實(shí)現(xiàn)接口的方法
public class RealSubject implements Subject {
@Override
public void visit() {
Log.e(TAG, "visit: ");
}
}
有了真實(shí)對(duì)象,我們就開(kāi)始準(zhǔn)備代理對(duì)象钳踊,在代理對(duì)象中衷敌,首先要注意實(shí)例化時(shí)要持有真實(shí)對(duì)象的引用。
public class ProxySubject implements Subject{
private RealSubject subject;
//獲取真實(shí)對(duì)象的引用
public ProxySubject(RealSubject subject) {
this.subject = subject;
}
@Override
public void visit() {
//通過(guò)真實(shí)對(duì)象調(diào)用方法
subject.visit();
}
}
編寫(xiě)好了以上代碼,我們就可以在測(cè)試類中使用代理模式了
public class Client {
public static void main(String args[]) {
//構(gòu)造真實(shí)對(duì)象
RealSubject rSub = new RealSubject();
ProxySubject pSub = new ProxySubject(rSub);
pSub.visit();
}
}
代碼看上去是很簡(jiǎn)單的, 也許你還是不清楚這個(gè)有什么用? 好吧 , 回到開(kāi)頭再點(diǎn)一次網(wǎng)址試試 , 一次不行就兩次 .
好了好了 , 言歸正傳 , 其實(shí)在編寫(xiě)代碼的時(shí)候 , 有時(shí)候還真的有不少的遇到點(diǎn)網(wǎng)址這樣類似的問(wèn)題 , 我們就需要通過(guò)代理去操作. 但是 , 代理模式不是需要代理對(duì)象和被代理對(duì)象都實(shí)現(xiàn)共同的接口么? 不要慌 , JDK中為我們提供了代理模式的模板 , 上面我們的代碼是靜態(tài)的代理模式 , 接下來(lái)我們來(lái)看看動(dòng)態(tài)的代理模式吧.
動(dòng)態(tài)的代理模式
動(dòng)態(tài)的代理模式, 是通過(guò)反射機(jī)制動(dòng)態(tài)地生成代理對(duì)象 , 我們?cè)诰幋a階段不需要知道代理誰(shuí) , 這個(gè)再執(zhí)行階段決定. java給我們提供了一個(gè)動(dòng)態(tài)代理接口: InvocationHandler
, 我們只需要實(shí)現(xiàn)這個(gè)接口的方法 , 并做微小的改動(dòng)就可以完成代理模式
public class MyProxy implements InvocationHandler{
//這里填入Object來(lái)接收任意類型
private Object obj;
public MyProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(obj, args);
return invoke;
}
}
在測(cè)試類中使用動(dòng)態(tài)代理
//動(dòng)態(tài)代理
//首先構(gòu)造真實(shí)對(duì)象
RealSubject realSubject = new RealSubject();
//準(zhǔn)備類加載器作為參數(shù)
ClassLoader loader = realSubject.getClass().getClassLoader();
//實(shí)例化代理,傳入真實(shí)對(duì)象
MyProxy myProxy = new MyProxy(realSubject);
//創(chuàng)造代理對(duì)象, 通過(guò)Proxy.newProxyInstance構(gòu)造
RealSubject fakeSub = (RealSubject) Proxy.newProxyInstance(loader, realSubject.getClass().getInterfaces(), myProxy);
//使用代理對(duì)象調(diào)用真實(shí)對(duì)象的方法
fakeSub.visit();
這里再說(shuō)一下invoke這個(gè)方法的參數(shù), 我們可以針對(duì)具體的業(yè)務(wù)來(lái)處理采納數(shù)
/**
* @param proxy 被代理對(duì)象
* @param method 被代理對(duì)象的方法
* @param args 被代理方法的參數(shù)
* @return 方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method為被代理的方法
Object result=method.invoke(target,args);
return result;
}