设计模式 - 代理模式
代理模式简介
定义:目标对象为其对象提供一种代理对象,其他对象通过代理对象来控制对目标对象的访问。
代理模式分为动态代理和静态代理,动态代理是在静态代理的基础上同过在Proxy层增加反射获取真正的被代理的对象来实现的。
1. 静态代理
1.1 使用场景
代理模式适合隔离底层业务逻辑具体细节的场景,比如说我们封装了一个图片加载的框架,但是这个框架会有可能会在将来的一个时间段过时,我们需要变更,但是变更前后整体的调用方式保存基本不变,可以考虑使用代理模式,同时目标对象无法直接访问或者访问存在困难的时候需要使用代理模式
1.2 角色:

Subject: 抽象主题类,生命真实主题和代理的共同接口方法。
RealISubject: 真实主题类,代理类所代表的的真实主题。客户端通过代理类间接的调用真实主题的方法。
Proxy: 代理类,持有真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
Client: 客户端类
1.3 代理模式的简单实现:
我多年没有回过哈尔滨了,很想念哈尔滨秋林红肠的味道。但是本人工作一直很忙抽不开身,不能亲自回到哈尔滨购买,于是就拖在哈尔滨的朋友帮忙购买秋林红肠。
1.3.1 定义抽象主题类
抽象主题类具有真实主题和代理类的共同接口方法,比如购买方法
public interface IShop {
void buy();
}
1.3.2 定义真实主题类
这个购买者Lile就是我本人,实现了IShop 接口提供的bug方法
public class Lile implements IShop {
@Override
public void buy() {
System.out.println("真正的购买实现!");
}
}
1.3.3 代理类
我找的代理同样要实现IShop接口,并且要持有代理者,在buy()方法中调用了被代理者的buy()方法
public class Proxy implements IShop {
private IShop mShop;
public Proxy(IShop shop) {
mShop = shop;
}
@Override
public void buy() {
mShop.buy();
}
}
1.3.4 客户端类
客户端通过代理完成购买动作
public class Client {
public static void main(String[] args) {
IShop lile = new Lile();
Proxy proxy = new Proxy(lile);
proxy.buy();
}
}
2. 动态代理
2.1 定义抽象主题类
抽象主题类具有真实主题和代理类的共同接口方法,比如购买方法
public interface IShop {
void buy();
}
2.2 定义动态代理类
public class DynamicPurchasiong implements InvocationHandler {
private String TAG = DynamicPurchasiong.class.getSimpleName();
private Object obj;
public DynamicPurchasiong(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(obj, args);
if ("buy".equals(method.getName())) {
Log.e(TAG,"Leli买它买它!");
}
return result;
}
}
2.3 客户端类
客户端通过代理完成购买动作
public static void main(String[] args) {
//创建真正的被代理的对象
IShop lile = new Lile();
//创建动态代理对象
DynamicPurchasiong dynamicPurchasiong = new DynamicPurchasiong(lile);
ClassLoader classLoader = lile.getClass().getClassLoader();
IShop proxy = (IShop) Proxy.newProxyInstance(classLoader, new Class[]{IShop.class}, dynamicPurchasiong);
proxy.buy();
}
输出结果
2021-06-24 17:57:31.238 31568-31568/smartliving.zbc.com.smartlivingapp E/Lile: 真正的购买实现!
2021-06-24 17:57:31.239 31568-31568/smartliving.zbc.com.smartlivingapp E/DynamicPurchasiong: Leli买它买它!
调用 Proxy.newProxyInstance() 来生成动态代理类,调用 purchasing 的 buy 方法会调用DynamicPurchasing 的 invoke 方法 。
3.代理模式的类型和优点
代理模式从编码角度分为静态代理和动态代理,如果从适用范围可以分为4种
-
远程代理: 为一个对象在不同的地址空间提供局部代表,这样系统可以将Server部分的实现隐藏
-
虚拟代理: 适用一个代理对象表示与一个十分耗费资源的对象并在真正需要时才会创建。
-
安全代理: 用来控制正式对象访问时的权限。一般用于真实对象有不同访问权限时。
-
智能引导: 当调用真实的对象时,代理处理另外一些事,比如计算真实对象的引用计数,当对象没有引用时,可以自动释放它;或者访问一个实际对象时,检查是否能够锁定它,以确保其他对象不能改变它。
代理模式有以下几个优点:
真实主题就是实际的业务逻辑,并不用关心其他非本职的工作。
真实主题随时都会发生变化;但是因为它实现了公共接口,所以代理类可以不做任何修饰就能够使用。
4. Android Retrofit 中的动态代理模式应用
通过我上面对Retrofit源码的截图,以及上面的标注就可以看出,这个Retrofit的creat()方法是个典型的动态代理的模式

5. 总结
优点:
-
1、代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;
-
2、代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了保护目标对象的作用。
缺点:
-
1、由于在客户端和真实对象之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢;
-
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。