代理模式UML
什么是代理模式?
給某個(gè)對(duì)象提供一個(gè)代理對(duì)象针肥,并由代理對(duì)象控制對(duì)于原對(duì)象的訪問(wèn),即客戶不直接操控原對(duì)象香伴,而是通過(guò)代理對(duì)象間接地操控原對(duì)象慰枕。
比如說(shuō),我想在喝星巴克的咖啡即纲;正常流程下具帮,我要自己去星巴克店里購(gòu)買,是我執(zhí)行買這個(gè)操作低斋,但現(xiàn)在我通過(guò)外賣服務(wù)蜂厅,這個(gè)買的人就變成了外賣小哥,而不是我本人膊畴,這里的外賣小哥其實(shí)就是我的代理掘猿,他代我實(shí)現(xiàn)了這個(gè)買的操作。這里的我相當(dāng)于Client唇跨,買咖啡是一個(gè)借口Subject稠通,外賣小哥就是ReallySubject,ProxySubject就是我要買咖啡的一個(gè)代理(我并不關(guān)心真正的執(zhí)行者是誰(shuí))
一個(gè)簡(jiǎn)單的代理實(shí)現(xiàn)代碼
public class Delegate {
public void main() {
// 真正執(zhí)行者
Subject reallySubject =new ReallySubject();
// 代理執(zhí)行者
Subject proxySubject =new ProxySubject(reallySubject);
// 看似是代理執(zhí)行者在做事【所謂的代理】
proxySubject.doSomethings();
}
}
interface Subject {
void doSomethings();
}
public class ReallySubjectimplements Subject {
@Override
public void doSomethings() {
Log.e("實(shí)際執(zhí)行人","真正要做事的");
}
}
public class ProxySubjectimplements Subject {
private Subjectsubject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void doSomethings() {
Log.e("我是代辦人","通知真正辦事的者买猖,辦事改橘!");
if (subject !=null)
subject.doSomethings();
}
}
什么是靜態(tài)代理和動(dòng)態(tài)代理?
靜態(tài)代理:在編譯時(shí)就將接口玉控、實(shí)現(xiàn)類飞主、代理類實(shí)現(xiàn)了,說(shuō)白點(diǎn)就是咱們自己手動(dòng)全部敲出來(lái)奸远。
動(dòng)態(tài)代理:在程序運(yùn)行時(shí)既棺,根據(jù)需要?jiǎng)討B(tài)的創(chuàng)建代理類及相關(guān)實(shí)例。
都是代理又為什么要區(qū)分靜態(tài)代理和動(dòng)態(tài)代理呢懒叛?
當(dāng)我們遇到某個(gè)需求要實(shí)現(xiàn)大量的代理的時(shí)候丸冕,每一個(gè)都要手動(dòng)去敲是一件很費(fèi)時(shí)操作,而且大部分的代碼又都是重復(fù)的薛窥,這個(gè)時(shí)候就有大神就提出了動(dòng)態(tài)代理的方案胖烛,來(lái)簡(jiǎn)化這些沒(méi)有營(yíng)養(yǎng)的操作了,即動(dòng)態(tài)代理的出現(xiàn)诅迷。
動(dòng)態(tài)代理的實(shí)現(xiàn)
public class DelegateSubject implements InvocationHandler {
private Subject subject;
public DelegateSubject(Subject subject) {
this.subject = subject;
}
/**
*
* @param proxy 代理對(duì)象(表示哪個(gè)代理對(duì)象調(diào)用了method方法)
* @param method 調(diào)用方法
* @param args 調(diào)用方法參數(shù)
* @return 代理實(shí)例調(diào)用具體的方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
// 添加自己的代碼1
// 根據(jù)自己的需要甚至可以不調(diào)用method.invoke()方法
object = method.invoke(subject, args);
// 添加自己的代碼2
return object;
}
}
public class Delegate {
public void main() {
// 真正執(zhí)行者
ReallySubject reallySubject = new ReallySubject();
// 代理執(zhí)行器
DelegateSubject delegateSubject = new DelegateSubject(reallySubject);
// 構(gòu)造動(dòng)態(tài)代理
// 第一個(gè)參數(shù) 真正執(zhí)行者加載器
// 第二個(gè)參數(shù) 真正執(zhí)行者實(shí)現(xiàn)的接口
// 第三個(gè)參數(shù) 代理執(zhí)行器
Subject subject = (Subject) Proxy.newProxyInstance(
ReallySubject.class.getClassLoader(),
ReallySubject.class.getInterfaces(), // 或者 new Class<?>[] { Subject.class },
delegateSubject);
// 通過(guò)代理執(zhí)行對(duì)象方法
// 調(diào)用此方法執(zhí)行 DelegateSubject的invoke()
subject.doSomethings();
}
}
看看retrofit是怎么使用動(dòng)態(tài)代理
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的代碼你會(huì)不會(huì)產(chǎn)生疑問(wèn)佩番,retrofit只有接口沒(méi)并沒(méi)有具體的執(zhí)行者啊0丈肌L宋贰!
還記得上面的這段代碼么滩租?
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
// 添加自己的代碼1
// 根據(jù)自己的需要甚至可以不調(diào)用method.invoke()方法
object = method.invoke(subject, args);
// 添加自己的代碼2
return object;
}
中提到過(guò) “根據(jù)需要你甚至可以不調(diào)用method.invoke()”赋秀,沒(méi)錯(cuò)retrofit就這么干的
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
這段代碼只要是使用OkHttp進(jìn)行網(wǎng)絡(luò)請(qǐng)求利朵,并將OkHttp的返回結(jié)果作為最終函數(shù)的返回結(jié)果。