本平臺的文章更新會有延遲,大家可以關注微信公眾號-顧林海,包括年底前會更新kotlin由淺入深系列教程,目前計劃在微信公眾號進行首發,如果大家想獲取最新教程,請關注微信公眾號,謝謝!
代理設計模式主要分為靜態代理與動態代理,代理模式的定義是為其他物件提供一種代理,用以控制對這個物件的訪問。打個比方:你人在國內,但是想要購買國外的某件商品,這時候你可以找朋友幫你買,你朋友就是代理,至於你朋友怎麼買你不關心,你只要拿到商品就行。
靜態代理
看上面這張類圖,靜態代理需要三個角色,一個是抽象物件角色(AbstractObject),一個是目標物件角色(RealObject),最後是代理物件角色(ProxyObject),在抽象物件角色類中定義了目標物件和代理物件的共同介面,RealObject是代理物件所代理的目標物件,ProxyObject是代理物件角色,內部會持有目標物件角色的引用,這樣的話可以通過代理物件執行目標物件內的方法,接下來看具體的程式碼實現。
抽象物件角色:
public abstract class AbstractObject {
protected abstract void operation();
}
複製程式碼
目標物件角色:
public class RealObject extends AbstractObject {
@Override
protected void operation() {
System.out.println("目標物件的方法");
}
}
複製程式碼
代理物件角色:
public class ProxyObject extends AbstractObject {
private AbstractObject mRealObject;
public ProxyObject(AbstractObject realObject){
this.mRealObject=realObject;
}
@Override
protected void operation() {
System.out.println("執行目標物件前的工作....");
this.mRealObject.operation();
System.out.println("執行目標物件後的工作....");
}
}
複製程式碼
在代理物件的operation方法中我們可以進行一些額外的操作,比如日誌的統計或者業務邏輯處理等。在日常開發中對已有的程式碼做改進,這時可以使用一個代理類對原有的結果進行控制。
動態代理
在Retrofit中使用到了動態代理,使用動態代理,可以無侵入式的擴充套件程式碼,在不改動原有程式碼的情況下,增強一些方法或功能,它的定義是:在程式執行時建立的代理方式。
接下來通過一個例項來了解動態代理:
public interface Subject {
void operation();
}
複製程式碼
建立了一個Subject介面,它是代理類和被代理類共同實現的一個介面。
public class RealObject implements Subject {
@Override
public void operation() {
System.out.println("目標物件的方法");
}
}
複製程式碼
RealObject是被代理物件,內部operation方法執行被代理類原有的方法。
public class ProxyObject implements InvocationHandler {
private Object mRealObject;
public ProxyObject(Object realObject){
this.mRealObject=realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("operation".equals(method.getName())){
System.out.println("哈哈,捕捉到operation方法,我要做點其他事情...");
return method.invoke(mRealObject,args);
}
return null;
}
}
複製程式碼
ProxyObject就是代理類,mRealObject代表真實的物件,ProxyObject需要實現InvocationHandler介面,並實現invoke方法,方法內部第一個引數proxy表示被代理的真實物件,第二個引數method表示真實物件的方法,第三個引數args表示真實物件的方法的引數。
public class Test {
public static void main(String[] args) {
Subject subject=new RealObject();
Subject proxyObject= (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(),
new Class<?>[]{Subject.class},
new ProxyObject(subject));
proxyObject.operation();
}
}
複製程式碼
通過Proxy的newProxyInstance方法建立代理類,傳入第一個引數是被代理類的ClassLoader,第二個引數是被代理實現的介面,第三個引數就是實現了InvocationHandler的物件。
執行結果:
哈哈,捕捉到operation方法,我要做點其他事情...
目標物件的方法
複製程式碼
在代理類ProxyObject的invoke方法中攔截到了operation方法,這時可以新增上我們需要的程式碼或功能。
搜尋微信“顧林海”公眾號,定期推送優質文章。