代理模式其實就是提供了對目標對象的另外的訪問方式,通過代理對象訪問目標對象
爲啥要這麼麻煩呢!!!其實是爲了不去修改原有的代碼,通過代理也可以訪問這個對象而且可以進行擴展
這種模式有什麼應用場景呢?先說下生活中對應的場景,明星接通告
一般商家要找明星做活動,是要先找到他的經紀人,然後經紀人去負責一些瑣碎的或者運營方面的事情,而明星只需要做具體的活動相關事情就可以了。這裏經紀人的作用就是作爲了一個代理。
靜態代理
首先是靜態代理,上代碼
/**
* 首先聲明一個接口,用於工作的接口
*/
public interface IStarDao {
void dowork();
}
/**
* 明星工作類
* 主要爲演戲
*/
public class SuperStarDao implements IStarDao {
@Override
public void dowork() {
//演戲工作
}
}
/**
* 經紀人代理類
* 主要是負責接活,並且安排明星工作,以及後續宣傳工作
*/
public class StarbrokerDaoProxy implements IStarDao {
private IStarDao starDao;
public StarbrokerDaoProxy(IStarDao starDao) {
this.starDao = starDao;
}
@Override
public void dowork() {
/*--接活--*/
starDao.dowork();//明星工作
/*--宣傳工作--*/
}
}
ok,至此明星和經紀人已經創建完畢,接下來就是怎麼去操作,首先找到具體的明星,然後找到對應的經紀人,也就是代理類,從而完成所有工作
public void main() {
SuperStarDao starDao = new SuperStarDao();
StarbrokerDaoProxy proxy = new StarbrokerDaoProxy(starDao);
proxy.dowork();
}
動態代理
動態代理的特點是不需要提前創建代理對象,而是利用反射機制在運行時創建代理類,從而動態實現代理功能
也就是說,這裏的明星不需要具體的經紀人了。有活動的時候,可以創建一個經紀人,可以是自己,可以是家人,然後完成原本代理的一些工作,見代碼
public void main() {
final IStarDao starDao = new SuperStarDao();
IStarDao proxy = (IStarDao) Proxy.newProxyInstance(
starDao.getClass().getClassLoader(),
starDao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*--接活--*/
Object returnValue = method.invoke(starDao, args);//明星工作
/*--宣傳工作--*/
return returnValue;
}
});
proxy.dowork();
}
在Android中的應用
Retrofit,想必大家都很熟悉,retrofit其實核心內容就是用了動態代理。
想想retrofit是怎麼工作的?在interface裏面寫上需要配置的請求方法,並添加一些註解
然後創建出interface的實例,就可以直接調用方法進行網絡請求了。
看看代碼:
public interface ApiService {
@POST(RetrofitHelper.APP_V1 + "/banner")
Observable<BaseEntity<List<Banner>>> getBanners();
}
ApiService mService = new Retrofit.Builder().baseUrl("").build().create(ApiService.class);
service.getBanners().enqueue(callback);
我們只是寫了ApiService接口和接口下面的getBanners方法,然後就可以進行網絡請求。
所以retrofit是代替我們寫了網絡請求的具體邏輯,也就是完成了代理的這樣一個作用。
具體怎麼代理的呢?
奧祕主要就在這個 create(ApiService.class)方法 裏面,看看源碼:
public <T> T create(final Class<T> 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 {
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
看到這個newProxyInstance方法了吧,這就是創建動態代理類的方法。
invoke方法裏面就是具體去拆解 接口裏面方法的一些參數,然後完成網絡請求的整個過程了,也就是代理幫你做的一些事情。
這裏順便就簡單說下這些源碼幹了什麼事,也方便大家自己研究源碼
- loadServiceMethod 主要是讀取接口裏面每個方法的註解,參數等等
- new OkHttpCall 主要是調用okhttp的一些方法,發起一些網絡請求
- adapt(okHttpCall) 主要是轉換OkHttpCall對象,並且切換到主線程
你的一個👍,就是我分享的動力❤️。