Java设计模式之代理模式

设计模式

在说代理模式之前先说说什么是设计模式吧。

简单来说设计模式就是用来解决不同问题的一种思路。这就很好理解了,就不如说你遇到了不同的问题,每个问题都有每个问题的解决方法。

代理模式

既然设计模式是用来解决不同问题的,那么接下来就来讲讲代理模式主要是用来解决什么问题的吧。

代理模式的意义在于能够帮助被代理对象做更多的事情,而不去破坏原先的代码结构。这里主要是在特定的业务环境中不能够去修改被代理类中的方法,但是却要增加某些功能,这就需要用到代理模式。其中mybatis 和spring aop就是很典型的例子。

代理模式其实就是面向接口编程,所以代理类和被代理类都要实现接口,当然还有例外就是cglib,它是通过继承在子类在覆盖原有的方法从而实现代理的。这里我主要说静态代理和动态代理。

静态代理

静态代理就是创建一个代理类去实现被代理类实现的接口。

这里先创建一个接口,其中有一个method方法

Java设计模式之代理模式_第1张图片

然后来实现这个接口,重写method方法。这时候就要加一个需求在method中加一句话,但是不能改动原先的代码。这时就需要用到代理模式了。

Java设计模式之代理模式_第2张图片

先创建一个代理类,然后也实现excouter接口

Java设计模式之代理模式_第3张图片

这里就能在method方法中写你要增加的代码了,这里分别在被代理对象的method方法执行前和执行后添加了一句话。

我们来执行一下,

Java设计模式之代理模式_第4张图片

Java设计模式之代理模式_第5张图片

这就实现了。

这里会说,不就是加一句话吗,至于这么麻烦吗?

这里我只是举个例子,在实际中接口中有可能有很多方法,但是之前写好方法因为新需求突然要加功能,如果你直接去改原方法的话,可能会对其他调用这个方法的其他代码引起冲突,我们是不推荐在原基础上去加或改的,因为如果出错找起来非常麻烦,也不便于维护。使用了代理模式就能够把你新增的方法和之前的代码区分开来,这样更好分辨,不用把代码都写一起看都不好看。日后出了问题也能很快定位。别人看代码的时候也更容易理解。

静态代理方式的优点

1. 易于理解和实现

2. 代理类和被代理类的关系是编译期静态决定的,和下文马上要介绍的动态代理比较起来,执行时没有任何额外开销。

静态代理方式的缺点

1.每一个被代理类都需要一个创建新的代理类。就比如说我在Excouter接口中新加了一个方法,这下不仅被代理类需要重写方法,代理类也需要重写方法,因为它们都是实现的同一个接口很好理解,但是这样工作量就很大也很繁琐。

2.如果我们要在多个接口增加的业务逻辑是相同的,就要重复编写代理类,造成代码重复。

 

正因为这些缺点就诞生了动态代理

动态代理

在写代理模式时,我们做的其实是面向接口编程,代理类和被代理类都实现了一个接口,这也是代理的规范写法。所以被代理类必须实现接口如果不实现接口就会报错。

实现动态代理的方法之一是通过实现

InvocationHandler 

这一接口来实现的

InvocationHandler 接口只需要实现invoke方法,三个参数依次为 代理对象(基本没什么用),代理对象调用的方法,调用的方法中的参数。通过
method.invoke方法,我们传入需要代理的对象(被代理对象作为MyProxy的成员对象,通过bind方法传入),和这个方法的参数,便可以调用被代理对象的原方法。然后其它跟静态代理没什么区别。
还有一点,method.getName()可以知道被代理对象调用了什么方法,根据不同方法可以自由编写增强现有代码的功能。

Java设计模式之代理模式_第6张图片

 

这里就是通过

Proxy.newProxyInstance这个方法来创建的代理对象

Proxy.newProxyInstance方法传入 被代理对象的classloader,接口和被代理对象本身。它会在代码运行时 自动创建代理对象(免去了自己写代理类的问题),然后通过返回的代理对象调用代理方法。

返回的代理对象jvm会加工,加工后类型为$Proxy(),当执行加工后的类型变量的方法时,jvm会转到代理类中的invoke方法去执行。

 

InvocationHandler具体可以看这篇文章Java动态代理之InvocationHandler

 


 

Java设计模式之代理模式_第7张图片

Java设计模式之代理模式_第8张图片

你可能感兴趣的:(java设计模式,java,设计模式,代理模式)