代理模式UML
圖1-1,代理模式UML建模
什么是代理模式?
給某個對象提供一個代理對象,并由代理對象控制對于原對象的訪問,即客戶不直接操控原對象,而是通過代理對象間接地操控原對象。
比如說,我想在喝星巴克的咖啡;正常流程下,我要自己去星巴克店里購買,是我執行買這個操作,但現在我通過外賣服務,這個買的人就變成了外賣小哥,而不是我本人,這里的外賣小哥其實就是我的代理,他代我實現了這個買的操作。這里的我相當于Client,買咖啡是一個借口Subject,外賣小哥就是ReallySubject,ProxySubject就是我要買咖啡的一個代理(我并不關心真正的執行者是誰)
一個簡單的代理實現代碼
public class Delegate {
public void main() {
// 真正執行者
Subject reallySubject =new ReallySubject();
// 代理執行者
Subject proxySubject =new ProxySubject(reallySubject);
// 看似是代理執行者在做事【所謂的代理】
proxySubject.doSomethings();
}
}
interface Subject {
void doSomethings();
}
public class ReallySubjectimplements Subject {
@Override
public void doSomethings() {
Log.e("實際執行人","真正要做事的");
}
}
public class ProxySubjectimplements Subject {
private Subjectsubject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void doSomethings() {
Log.e("我是代辦人","通知真正辦事的者,辦事!");
if (subject !=null)
subject.doSomethings();
}
}
什么是靜態代理和動態代理?
靜態代理:在編譯時就將接口、實現類、代理類實現了,說白點就是咱們自己手動全部敲出來。
動態代理:在程序運行時,根據需要動態的創建代理類及相關實例。
都是代理又為什么要區分靜態代理和動態代理呢?
當我們遇到某個需求要實現大量的代理的時候,每一個都要手動去敲是一件很費時操作,而且大部分的代碼又都是重復的,這個時候就有大神就提出了動態代理的方案,來簡化這些沒有營養的操作了,即動態代理的出現。
動態代理的實現
public class DelegateSubject implements InvocationHandler {
private Subject subject;
public DelegateSubject(Subject subject) {
this.subject = subject;
}
/**
*
* @param proxy 代理對象(表示哪個代理對象調用了method方法)
* @param method 調用方法
* @param args 調用方法參數
* @return 代理實例調用具體的方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
// 添加自己的代碼1
// 根據自己的需要甚至可以不調用method.invoke()方法
object = method.invoke(subject, args);
// 添加自己的代碼2
return object;
}
}
public class Delegate {
public void main() {
// 真正執行者
ReallySubject reallySubject = new ReallySubject();
// 代理執行器
DelegateSubject delegateSubject = new DelegateSubject(reallySubject);
// 構造動態代理
// 第一個參數 真正執行者加載器
// 第二個參數 真正執行者實現的接口
// 第三個參數 代理執行器
Subject subject = (Subject) Proxy.newProxyInstance(
ReallySubject.class.getClassLoader(),
ReallySubject.class.getInterfaces(), // 或者 new Class<?>[] { Subject.class },
delegateSubject);
// 通過代理執行對象方法
// 調用此方法執行 DelegateSubject的invoke()
subject.doSomethings();
}
}
看看retrofit是怎么使用動態代理
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
看了retrofit的代碼你會不會產生疑問,retrofit只有接口沒并沒有具體的執行者啊!!!
還記得上面的這段代碼么?
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
// 添加自己的代碼1
// 根據自己的需要甚至可以不調用method.invoke()方法
object = method.invoke(subject, args);
// 添加自己的代碼2
return object;
}
中提到過 “根據需要你甚至可以不調用method.invoke()”,沒錯retrofit就這么干的
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
這段代碼只要是使用OkHttp進行網絡請求,并將OkHttp的返回結果作為最終函數的返回結果。