代理设计模式浅析
概述
代理设计模式的应用可以说是非常之广泛。比如说 Retrofit封装OkHttp,就是用的动态代理的方式,生成了代理接口的对象(create 方法),从而代理 OkHttp生成网络请求的 Call对象。看代理模式定义:为其他对象提供一种代理以控制对这个对象的访问。结合现实生活来描述,就比如说客户取银行柜台办卡,那么客户就是被代理者,银行柜员则代理客户办卡。代理模式分为静态代理和动态代理,在日常开发过程中我们可能见到动态代理多一点。下面看一下。
一、静态代理
下面就拿柜员帮客户办卡来看看静态代理。先创建一个抽象业务:
public interface IProxy {
void play(); // 办卡
}
下面创建办卡客户类型,继承 IProxy :
/**
* 办卡客户
*/
public class Customer implements IProxy{
private static final String TAG = "TAG_Customer";
@Override
public void play() {
Log.d(TAG, "帮我办卡就好");
}
}
客户 play() 方法里执行办卡操作,再来一个银行柜员,也是继承自 IProxy:
/**
* 银行柜员
*/
public class Banker implements IProxy{
private static final String TAG = "TAG_Banker";
// 持有客户(被代理者)对象
private IProxy mCustomer;
public Banker(IProxy customer){
this.mCustomer = customer;
}
@Override
public void play() {
Log.d(TAG, "我来帮您办卡,需要办会员吗?");
this.mCustomer.play(); // 办卡
Log.d(TAG,"您好,卡给您办完了");
}
}
上面可以看到,银行柜员将持有客户的对象(mCustomer),调用了客户办卡的play()方法,这就是代理。与此同时上面 Log我们可以看到,银行柜员帮客户办卡的同时还可以做些别的事,比如说推销办会员啊、推销理财产品啊啥的。下面看调用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Banker banker = new Banker(new Customer()); // 创建代理者
banker.play(); // 代理者开始操作
}
}
// Log
D/TAG_Banker: 我来帮您办卡,需要办会员吗?
D/TAG_Customer: 帮我办卡就好
D/TAG_Banker: 您好,卡给您办完了
二、动态代理
开头说了,动态代理在日常开发中应用还是很广泛的。就比如大名鼎鼎的 Retrofit的核心实现就是靠动态代理。
动态代理是通过反射来生成被代理类对象的,所以在源码阶段不需要知道被代理者的类型。这样的好处就是解耦。java提供了一个便捷的动态代理接口 InvocationHandler,被代理者的方法就是在该接口实现类的 invoke方法里被调用。下面写一个 InvocationHandler实现类:
public class ProxyHandler implements InvocationHandler {
private static final String TAG = "ProxyBanker";
private Object mCustomer;
public ProxyHandler(Class<?> customer){
try {
// 反射生成对象
mCustomer = customer.newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 反射调用被代理者对象
Object object = method.invoke(mCustomer, args);
return object;
}
}
可以看到上面构造方法参数类型是被代理者的 Class类型,所以这里不需要提前知道被代理者是啥类型,因为被代理者对象通过反射生成,这里这样做也是为了解耦。然后被代理者的方法也是被动态调用。下面来看一下使用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 动态传入类型
IProxy proxy = initProxy(Customer.class);
// 调用
proxy.play();
}
private <T extends Object> T initProxy(Class<T> clz){
// ProxyHandler 的参数类型是 Class,无论是什么样的被代理者都可以
ProxyHandler handler = new ProxyHandler(clz);
// 获取被代理者实现的的接口
Class interfaceClass = clz.getInterfaces()[0];
// 动态构建一个
T pBanker = (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class[]{interfaceClass},handler);
return pBanker;
}
}
我们可以看到上面,initProxy()方法,我们只需要把被代理者的类型(Customer.class)作为参数传入,即可动态生成代理者对象,然后调用相关方法。initProxy()方法相当于是一个简单的封装,只要我们封装好了就可以给外界使用,并且完全解耦。