徹底明白Android設計模式—(動態)代理模式

代理模式其實就是提供了對目標對象的另外的訪問方式,通過代理對象訪問目標對象
爲啥要這麼麻煩呢!!!其實是爲了不去修改原有的代碼,通過代理也可以訪問這個對象而且可以進行擴展

這種模式有什麼應用場景呢?先說下生活中對應的場景,明星接通告
一般商家要找明星做活動,是要先找到他的經紀人,然後經紀人去負責一些瑣碎的或者運營方面的事情,而明星只需要做具體的活動相關事情就可以了。這裏經紀人的作用就是作爲了一個代理。

靜態代理

首先是靜態代理,上代碼

 /**
     * 首先聲明一個接口,用於工作的接口
     */
    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對象,並且切換到主線程

你的一個👍,就是我分享的動力❤️。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章