1.我理解的代理设计模式
字面意思是代为处理的意思。举个例子:
- 需求:出一盘菜
- 处理方式:厨师炒一盘就行了
- 问题:口味不满足我的要求怎么办
再举个项目中的例子
- 需求:上传文件到服务器
- 处理方式:去github找个网络相关项目,实现上传文件
- 问题:那个项目实现了上传文件,但是我想监听上传的进度,实时显示出来怎么办
这就需要代理模式了,我自己来处理这些事,同时加上我自己想要的功能
- 我自己炒菜,满足需求了,我炒菜的同时我还可以依照自己的口味多加点酱油
- 上传文件时,我写个子类继承上传文件操作,这样不影响框架的其他功能,同时在上传文件时我还可以加点操作,每隔100ms获取一下上传了多少反馈出去
这就是代理模式,你已经实现了这个功能,但是我来做个代理,原先实现的我原封不动照办,但是会加点自己的东西
2.Java中动态代理
首先有个接口,可以做炒菜操作
public interface ICook {
public void doCook();
}
复制代码
来个实体类,实现这个接口
public class Man implements ICook {
@Override
public void doCook() {
System.out.println("出菜");
}
}
复制代码
出菜了
Man man = new Man();
man.doCook();
复制代码
接下来在改变Man中doCook()方法,在炒菜前加点香葱 用来动态代理的类
public class CookInvocationHandler implements InvocationHandler{
/**
* 被代理的对象
*/
private Object mObject;
public CookInvocationHandler(Object object){
this.mObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("加点香葱");
Object object = method.invoke(mObject,args);
return object;
}
}
复制代码
使用代理来出菜
public static void main(String[] args) {
Man man = new Man();
ICook cooker =
(ICook) Proxy.newProxyInstance(
ICook.class.getClassLoader(), // ClassLoader
new Class<?>[]{ICook.class}, // 目标接口
new CookInvocationHandler(man) // InvocationHandler
);
// 当调用这个方法的时候调用 CookInvocationHandler的invoke 法
cooker.doCook();
}
复制代码
3.应用场景
Retrofit
的创建就是使用了这个设计模式
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 the method is a method from Object then defer to normal invocation.
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);
}
});
}
复制代码
好处是,将内部网络请求和外部调用充分的解耦