设计模式-代理模式

前言

  前段时间我们分析了kotlin的委托,委托实际上有点类似于静态代理模式,趁着委托的记忆还没有消失(我的记忆力比鱼稍微好一丢丢(理直气壮)),我们来分析下代理模式。

静态代理

  静态代理模式中,有3个重要的角色

  1. 协议,它抽离了代理类和真实类的共性;
  2. 代理类,直接与客户进行交互,在内部访问真实类,但同时又可以对真实类的访问附加额外的操作;
  3. 真实类,代理类中真正操作的。

协议

  首先我们定义一个抽象接口,它有一个request方法。

1
2
3
interface IBase{
fun request()
}

真实类

  然后,我们定义一个真实类,它实现了协议。

1
2
3
4
5
class BaseImpl:IBase{
override fun request(){
//...request
}
}

代理类

  最后,我们定义一个代理类,它同样也实现了协议,同时它包含了一个真实类的实例对象。

1
2
3
4
5
6
7
8
9
10
class BaseImplProxy:IBase{
private val baseImpl:BaseImpl by lazy{
BaseImpl()
}

override fun request(){
//这里实际调用真实角色的request()
baseImpl.request()
}
}

  写到这里,我们发现上面和kotlin的委托是一模一样的原理。但是静态代理中,我们可以在request()中做一些额外的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
override fun request(){
preRequest()
baseImpl.request()
postRequest()
}

private fun preRequest(){
//...请求前做的事情
}

private fun postRequest(){
//...请求后做的事情
}

  kotlin的委托就不能做这些事情。

动态代理

  Java中的动态代理,我们得认识两个玩意,一个是InvocationHandler,一个是Proxy,它们位于reflect包下面。

协议

  动态代理中,我们同样需要定义协议。

1
2
3
interface IBase{
fun request()
}

真实类

  然后我们定义一个真实类。

1
2
3
4
class BaseImpl : IBase{
override fun request(){
}
}

实现InvocationHandler

  然后我们需要实现InvocationHandler接口,里面包含有一个BaseImpl的实例对象。

1
2
3
4
5
6
7
8
9
10
11
class InvocationHandlerImpl : InvocationHandler {

private val baseImpl:BaseImpl by lazy{
BaseImpl()
}

override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
return method?.invoke(baseImpl, args)
}

}

创建代理类

  一般我们会通过Proxy.newProxyInstance()创建代理类,它接受ClassLoader, Class<?>[]和一个InvocationHandler。

1
2
val clazz = IBaseImpl::class.java
val iBase:IBase = Proxy.newProxyInstance(clazz.classLoader, clazz.interfaces, object: InvocationHandlerImpl(){}) as IBase

  这样我们通过iBase对象调用request()的时候实际上会被回调到InvocationHandler的invoke(),而我们在invoke()中调用了BaseImpl的request()。

Retrofit的动态代理

  我们知道Retrofit里面使用了动态代理模式的。我们可以翻看它的源码,在Retrofit.java文件的create()中我们可以看到有动态代理的调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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, Object... args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}

  比如我们定义如下一个接口请求。

1
2
3
4
5
6
7
8
interface AdsService {

@POST("v4/client/ad/config")
fun fetchAdsInfo(
@Body reqBean: AdsReqBean
): Single<Response<BaseRespBean<AdsRespBean>>>

}

  然后通过Retrofit的create()方法,我们就可以得到一个AdsService的代理对象了。

本文标题:设计模式-代理模式

文章作者:严方雄

发布时间:2018-04-18

最后更新:2018-09-13

原始链接:http://yanfangxiong.com/2018/04/18/设计模式-代理模式/

0%