Android 代理模式
Android 設計模式系列文章Android 23種設計模式
前言
代理模式可能是我們平時開發中最常見的模式之一了。顧名思義,代理模式主要體現在代理二字上。比如我們買房的時候,通常我們會找一箇中介。而這個中介就是一個代理的角色。那麼代理模式在程式碼上的體現就是通過代理類來控制訪問需要被代理的類。
代理模式定義
為其他物件提供一種代理以控制這個物件的訪問。
代理模式舉例
Android中的代理模式十分常見,根據程式碼來歸類。主要分為靜態代理模式和動態代理模式。
1、靜態代理
靜態代理很好理解就是我們需要編寫一個代理類。實現我們需要代理的所有方法。所以稱之為靜態代理。由於需要代理的方法可能有很多。為了約束代理類和被代理類這些相同的方法,所以寫一個介面來繼承是最直觀的方式,當然這個介面不是必須的,可加可不加。都不影響,主要是理解代理這個設計模式的思想。代理模式的變化也很多。
public interface ProxyInterface { void choiceBetterHouse(); //模擬挑選優質房子 void buyHouse(); //模擬買房子 }
然後我們定義一個叫Petter的人
public class Petter implements ProxyInterface { private static final String TAG = Petter.class.getSimpleName(); @Override public void choiceBetterHouse() { Log.d(TAG,"挑選優質房子"); } @Override public void buyHouse() { Log.d(TAG,"買房子"); } }
然後定義代理類
public class StaticProxy implements ProxyInterface { private Petter petter; public StaticProxy(Petter petter) { this.petter = petter; } @Override public void choiceBetterHouse() { petter.choiceBetterHouse(); } @Override public void buyHouse() { petter.buyHouse(); } }
然後就是呼叫
Petter petter = new Petter(); StaticProxy agency = new StaticProxy(petter); agency.choiceBetterHouse(); agency.buyHouse();
輸出這裡就不列印了。靜態代理就是這麼簡單。就是代理petter挑選優質房子,買房子。賣家接觸的都是中介,真正執行和做決定的是Petter。現實程式碼中我們見得多的也就是這種代理了。
2、動態代理
動態代理和靜態代理的區別就是動態代理不用我們去手動編寫代理類。動態代理就是JDK提供的機制,可在記憶體中動態的生成代理類。
例子還是上面的例子,我們重新編寫動態代理類
public class DynamicProxy implements InvocationHandler { private static final String TAG = DynamicProxy.class.getSimpleName(); private Object object; public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Log.d(TAG,"invoke"); Object result = method.invoke(object,args); return result; } }
動態代理的核心就是繼承InvocationHandler這個介面,通過method的invoke方法來間接呼叫原本的方法。這裡和java反射呼叫方法的時候一樣。
然後我們看客戶端是如何呼叫的
Petter petter = new Petter(); // 返回一個代理物件 ProxyInterface proxyPetter = (ProxyInterface) Proxy.newProxyInstance( petter.getClass().getClassLoader(), petter.getClass().getInterfaces(), new DynamicProxy(petter)); proxyPetter.choiceBetterHouse(); proxyPetter.buyHouse();
這裡就是最關鍵的一步了,Proxy.newProxyInstance來生成一個代理物件。通過這個代理物件就可以呼叫需要被代理的方法了。我們來看輸出
01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/DynamicProxy: invoke 01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/Petter: 挑選優質房子 01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/DynamicProxy: invoke 01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/Petter: 買房子
好了,動態代理模式就這點兒東西了。比較的時候,注意對比StaticProxy、DynamicProxy的程式碼就可以了。
寫在最後
1、通常我們見得最多的就是靜態代理模式,靜態代理模式目的也很明確,代理需要代理的方法即可
2、代理模式是一種比較簡單的模式,通常我們使用的時候往往夾雜著其他比較複雜的知識。比如Android原始碼中,系統各種Service服務框架跨程序使用binder呼叫的時候就使用代理模式。這裡就不擴充套件開了,有興趣的同學可以看下我另一篇文章PackageManagerService服務框架詳解
3、雖然代理模式是一種相對簡單的模式,但它十分重要。學設計模式主要理解它的理念,知道使用它的優點。自然做到心中有數。不然就是知其然不知其所以然。