前言
代理模式可能是我們平時開發中最常見的模式之一了。顧名思義,代理模式主要體現在代理二字上。比如我們買房的時候,通常我們會找一個中介。而這個中介就是一個代理的角色。那么代理模式在代碼上的體現就是通過代理類來控制訪問需要被代理的類。
代理模式定義
為其他對象提供一種代理以控制這個對象的訪問。
代理模式舉例
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、雖然代理模式是一種相對簡單的模式,但它十分重要。學設計模式主要理解它的理念,知道使用它的優點。自然做到心中有數。不然就是知其然不知其所以然。