前言:
开发了多年,看了不少源码,发现许多源码涉及到设计模式很多,比如常见的单例、工厂以及建造者模式等等。今天为大家介绍下代理设计模式,静态代理与动态代理的区别所在,以及业务场景。
代理模式又称为委托模式,主要分为
- 静态代理
- 动态代理
代理模式的设计里面是限制对对象的直接访问,要想访问具体对象需要通过该对象的代理类去访问。
静态代理
静态代理主要分为下面三个部分:
- 抽象接口 ISubject
- 具体对象 RealSubject
- 代理对象 ProxySubject
举个生活中我们使用第三方支付的例子
创建购物抽象类:IPay
public interface IPay{
void pay();
}
创建具体实际的第三方支付抽象类:(比如微信支付)
public class WechatPay implements IPay {
@Override
public void pay() {
System.out.println("执行了微信支付功能");
}
}
创建代理类:
public class ProxyPay implements IPay {
/**
* 实际上支付的对象
*/
private IPay ipay;
public ProxyShop(IPay ipay) {
this.ipay= ipay;
}
@Override
public void pay() {
System.out.println("使用APP微信支付");
ipay.pay();
System.out.println("微信已支付,等待后端回调结果");
}
}
创建测试类:
public class Main {
public static void main(String[] args) {
WechatPay wechatPay= new WechatPay ();
ProxyPay proxyPay = new ProxyPay (wechatPay);
proxyPay.pay();
}
}
结果
可以看到,微信支付 帮我们完成了支付操作,并且在代理类过程中,可以增加一些特殊的操作,在支付操作的前后可以增加自定义操作。
动态代理
上面讲了静态代理,我们需要预先把需要的情况都要列出来,然后编写代理代码,需要自己生成编写代理类。
而动态代理就可以在运行时通过 Proxy.newProxyInstance生成代理类,比如我们有了新的需求,让朋友帮我们交话费,这个时候,就需要创建交话费的抽象,然后创建充话费的代理,这是很麻烦的,下面通过动态代理模式实现。
下面仍然以购物为例
抽象支付:
public interface IPay{
void pay();
}
实际代理对象:WechatPay
public class WechatPay implements IPay {
@Override
public void pay() {
System.out.println("执行了微信支付功能");
}
}
动态代理:
public class DynamicProxyHandler implements InvocationHandler {
Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用APP微信支付");
method.invoke(target,args);
System.out.println("微信已支付,等待后端回调结果");
return null;
}
}
测试类:
public class Main {
public static void main(String[] args) {
WechatPay wechatPay= new WechatPay ();
DynamicProxyHandler dynamicProxyHandler = new DynamicProxyHandler(wechatPay);
IPay ipay= (IPay ) Proxy.newProxyInstance(WechatPay .class.getClassLoader(),WechatPay .class.getInterfaces(),dynamicProxyHandler);
ipay.pay();
}
}
结果输出如上图一样。
总结:可以看到,我们可以在方法具体执行的前后加入一些自定义逻辑,更加灵活,而且在没修改原来方法的情况下,可以增强代码功能。
通过上面的实例可以发现:
静态代理的代理类需要自己编写,而动态代理的代理类则是由运行时使用 newProxyInstance 动态生成,
同时不管是静态代理还是动态代理,都需要实现接口,本质上是面对接口编程的,能够增加现有代码的功能。
区别 :
静态代理
静态代理业务类只需要关注业务逻辑本身,保证了业务类的重用性。代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,需要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法,增加了代码维护的复杂度。
动态代理
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler invoke)。这样,在接口方法数量比较多的时候,可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使类职责更加单一,复用性更强。