代理模式是开发中非常常见的一种设计模式,属于结构型模式。代理模式的动机简单点说就是,有时不方便或者不能直接访问一个对象时,可以通过一个代理对象来实现间接访问。在现实中有很多类似的例子:不想走那么远去火车站买票,就去近一点的代售点买票。不方便约明星谈合作,就和明星的经纪人谈。没有带现金,于是用手机微信作为代理买单。下面就具体分析代理模式以及动态代理的原理。
代理模式(Proxy Pattern)
定义
给某个对象提供一个代理,并由代理对象控制原对象的引用。属于对象结构型模式。
结构
代理模式主要包括三个角色:
Subject,对象的接口
RealSubject,实际对象
ProxySubject,代理对象,持有实际对象的引用
代理模式比较简单,就不再描述示例代码了。
有两点需要注意的:代理对象与实际对象实现相同的接口;代理对象持有实际对象的引用,调用代理对象方法最终会调用实际对象的实现。
与其他模式的区别
代理模式提供的接口不变,适配器模式是为实际对象提供一个不同的接口,装饰器模式是提供一个额外的接口。
代理模式和装饰器模式的结构非常相似,都持有原有对象的引用。
动态代理
上面代理模式的实现是静态代理,还有运行时生成代理类的动态代理,比较常见的是 Java 中动态代理机制,Retrofit 框架就是通过 Java 的动态代理把方法调用转换为网络请求。
Java 动态代理机制
先看下如何使用:
|
|
上面代码的输出:
|
|
Java 动态代理机制的原理
代理对象是通过Proxy.newProxyInstance
方法生成的,代理对象的类通过 jd-jui 工具反编译后大致如下:
|
|
动态生成的代理类继承自java.lang.reflect.Proxy
类,实现了需要代理的接口 Subject,而静态代理中代理类是我们自己写出来的。
动态代理的调用链:调用 proxyObject 方法 -> InvocationHandler.invoke -> 调用 realObject 方法
静态代理的调用链:调用 proxyObject 方法 -> 调用 realObject 方法
Java 动态代理机制的优缺点
优点:
解耦代理类与实际类,InvocationHandler 中传入的实际对象是不确定的,代理类不知道代理的具体是哪个对象。
减少代码量,代理多个接口时,InvocationHandler 实现可以不变
可以实现切片编程(AOSP)
缺点:
生成代理对象时使用了反射,性能有所下降。
Java 动态代理只能根据接口创建,不能根据类或抽象类创建。
参考文章