代理模式

代理模式:为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用。

假设一个场景:明星需要出演活动(比如唱歌),那么他需要签合同,收款等工作。但是对于明星来讲,这都是琐碎的事情,而且亲自来做,比较掉价,所以明星们一般都会设置一个代理(也就是经纪人),经纪人负责签合同,收款等这些琐碎的工作,明星本人只需要专注于唱歌这一件事情就可以了。

使用代理模式的好处:

  • 被代理类可以更加专注于主要功能的实现
  • 代理类可以在被代理类已经存在的功能上添加新的功能

我们用代码来模拟这个过程。

静态代理:

写一个Star接口

 1 package top.bigking.proxy.staticProxy;
 2 
 3 /**
 4  * @Author ABKing
 5  * @Date 2020/2/14 下午9:33
 6  **/
 7 public interface Star {
 8     /**
 9      * 签合同
10      */
11     public void signContract();
12     /**
13      * 唱歌
14      */
15     public void sing();
16     /**
17      * 收尾款
18      */
19     public void collectMoney();
20 }

让明星RealStar类实现这个接口:

 1 package top.bigking.proxy.staticProxy;
 2 
 3 /**
 4  * @Author ABKing
 5  * @Date 2020/2/14 下午10:01
 6  **/
 7 public class RealStar implements Star {
 8     @Override
 9     public void signContract() {
10         System.out.println("ReadStar.signContract");
11     }
12 
13     @Override
14     public void sing() {
15         System.out.println("蔡徐坤本人唱歌");
16     }
17 
18     @Override
19     public void collectMoney() {
20         System.out.println("ReadStar.collectMoney");
21     }
22 }

让代理ProxyStar类实现这个接口:

 1 package top.bigking.proxy.staticProxy;
 2 
 3 /**
 4  * @Author ABKing
 5  * @Date 2020/2/14 下午10:02
 6  **/
 7 public class ProxyStar implements Star {
 8     private Star star;
 9 
10     public ProxyStar(Star star) {
11         this.star = star;
12     }
13 
14     @Override
15     public void signContract() {
16         System.out.println("ProxyStar.signContract");
17     }
18 
19     @Override
20     public void sing() {
21         star.sing();
22     }
23 
24     @Override
25     public void collectMoney() {
26         System.out.println("ProxyStar.collectMoney");
27     }
28 }

进行JUnit测试:

 1 package top.bigking.proxy.staticProxy;
 2 
 3 import org.junit.Test;
 4 
 5 /**
 6  * @Author ABKing
 7  * @Date 2020/2/14 下午10:04
 8  **/
 9 public class TestStaticProxy {
10     @Test
11     public void testStaticProxy(){
12         Star realStar = new RealStar();
13         Star proxyStar = new ProxyStar(realStar);
14         proxyStar.signContract();
15         proxyStar.sing();
16         proxyStar.collectMoney();
17     }
18 }

结果如下:

ProxyStar.signContract
蔡徐坤本人唱歌
ProxyStar.collectMoney

 

动态代理:

JDK动态代理:

Star接口和RealStar类不变

写一个StarHandler类:

 1 package top.bigking.proxy.dynamicProxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 /**
 7  * @Author ABKing
 8  * @Date 2020/2/14 下午11:16
 9  **/
10 public class StarHandler implements InvocationHandler {
11     private Star star;
12 
13     public StarHandler(Star star) {
14         this.star = star;
15     }
16 
17     @Override
18     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
19         if(method.getName().equals("sing")) {
20             method.invoke(star, args);
21         }
22         System.out.println(method.getName());
23         return null;
24     }
25 }

执行JUnit单元测试:

 1 package top.bigking.proxy.dynamicProxy;
 2 
 3 import org.junit.Test;
 4 
 5 import java.lang.reflect.Proxy;
 6 
 7 /**
 8  * @Author ABKing
 9  * @Date 2020/2/14 下午11:22
10  **/
11 public class TestDynamicProxy {
12     @Test
13     public void testDynamicProxy(){
14         Star realStar = new RealStar();
15         StarHandler starHandler = new StarHandler(realStar);
16         Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
17                 new Class[]{Star.class}, starHandler);
18         proxy.signContract();
19         proxy.sing();
20         proxy.collectMoney();
21     }
22 }

运行结果如下:

signContract
蔡徐坤本人唱歌sing
collectMoney

开发框架中应用场景:

  • Struts2中拦截器的实现
  • 数据库连接池关闭处理
  • Hibernate中延时加载的实现
  • mybatis中实现拦截器插件
  • AspectJ的实现
  • spring中AOP的实现:日志拦截,声明式事务处理
  • web service
  • RMI远程方法调用
金麟岂是池中物,一遇风云便化龙!
原文地址:https://www.cnblogs.com/ABKing/p/12309931.html