GOF23设计模式之代理模式(proxy)

一、代理模式概述

  1、代理模式的核心作用

    (1)通过代理,控制对象的访问;

    (2)可以详细的控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(AOP的微实现)

        代理模式是 AOP(Aspect Oriented Programming 面向切面编程)的核心实现机制。

  2、代理模式的核心角色

    (1)抽象角色

      定义代理角色和真实角色的公共对外方法。

    (2)真实角色

      实现抽象角色,定义真实角色所需要实现的业务逻辑,供代理角色调用。

      关注真正的业务逻辑。

    (3)代理角色

      实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑辅方法来实现抽象方法,并附加自己的操作。

      将统一的流程控制放在代理角色中处理!

  3、代理模式的使用场景

    (1)安全代理: 屏蔽对真实角色的访问;

    (2)通过代理类处理远程方法调用(RMI Remote Method Invocation 远程方法调用);

    (3)延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。

  4、代理模式的分类

    (1)静态代理(静态定义代理类)

    (2)动态代理(动态生成代理类)

      ① JDK自带的动态代理

      ② javassist字节码操作库实现

      ③ CGLIB

        CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。

        通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。

      ④ ASM底层使用指令,可维护性较差

        ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。

二、代理模式之静态代理

  示例代码场景:周杰伦开演唱会时,面谈、签合同、订票等操作都是由周杰伦的经纪人来完成,唱歌部分由他本人完成,最后收款也是由经纪人来完成。

  (1)创建抽象角色

 1 /**
 2  * 抽象角色
 3  * @author CL
 4  *
 5  */
 6 public interface Star {
 7     /**
 8      * 面谈 
 9      */
10     void confer();
11     /**
12      * 签合同
13      */
14     void signConstract();
15     /**
16      * 订票
17      */
18     void bookTicket();
19     /**
20      * 唱歌
21      */
22     void sing();
23     /**
24      * 收款
25      */
26     void collectMoney();
27 }

  (2)定义真实角色

 1 /**
 2  * 真实身份(相当于例子中的周杰伦本人)
 3  * @author CL
 4  *
 5  */
 6 public class RealStar implements Star {
 7 
 8     @Override
 9     public void confer() {
10         System.out.println("周杰伦去面谈");
11     }
12 
13     @Override
14     public void signConstract() {
15         System.out.println("周杰伦去签合同");
16     }
17 
18     @Override
19     public void bookTicket() {
20         System.out.println("周杰伦去订票");
21     }
22 
23     @Override
24     public void sing() {
25         System.out.println("周杰伦去唱歌");
26     }
27 
28     @Override
29     public void collectMoney() {
30         System.out.println("周杰伦去收款");        
31     }
32 
33 }

  (3)定义代理角色

 1 /**
 2  * 代理身份(相当于例子中的周杰伦的经纪人)
 3  * @author CL
 4  *
 5  */
 6 public class ProxyStar implements Star {
 7     private Star star;
 8     
 9     public ProxyStar(Star star) {
10         this.star = star;
11     }
12 
13     @Override
14     public void confer() {
15         System.out.println("经纪人去面谈");
16     }
17 
18     @Override
19     public void signConstract() {
20         System.out.println("经纪人去签合同");
21     }
22 
23     @Override
24     public void bookTicket() {
25         System.out.println("经纪人去订票");
26     }
27 
28     @Override
29     public void sing() {
30         star.sing();
31     }
32 
33     @Override
34     public void collectMoney() {
35         System.out.println("经纪人去收款");
36     }
37 
38 }

  (4)测试

 1 /**
 2  * 客户端
 3  *     只和经纪人联系
 4  * @author CL
 5  *
 6  */
 7 public class Client {
 8 
 9     public static void main(String[] args) {
10         Star real = new RealStar();
11         Star proxy = new ProxyStar(real);
12         
13         //面谈
14         proxy.confer();
15         //签合同
16         proxy.signConstract();
17         //订票
18         proxy.bookTicket();
19         //唱歌
20         proxy.sing();
21         //收款
22         proxy.collectMoney();
23     }
24 }

  控制台输出:

经纪人去面谈
经纪人去签合同
经纪人去订票
周杰伦去唱歌
经纪人收款

三、代理模式之动态代理

  JDK自带的动态代理:

    ① 在客户端,java.lang.reflect.Proxy

     作用:动态生成代理类和对象

    ② 实现java.lang.reflect.InvocationHandler(处理器接口)

     可以通过invoke方法实现对真实角色的代理访问

     每次通过Proxy生成代理类对象时都要指定对应的处理器对象

  (1)创建抽象角色

 1 public interface Star {
 2     /**
 3      * 面谈 
 4      */
 5     void confer();
 6     /**
 7      * 签合同
 8      */
 9     void signConstract();
10     /**
11      * 订票
12      */
13     void bookTicket();
14     /**
15      * 唱歌
16      */
17     void sing();
18     /**
19      * 收款
20      */
21     void collectMoney();
22 }

  (2)创建真实角色

 1 /**
 2  * 真实身份(相当于例子中的周杰伦本人)
 3  * @author CL
 4  *
 5  */
 6 public class RealStar implements Star {
 7 
 8     @Override
 9     public void confer() {
10         System.out.println("周杰伦去面谈");
11     }
12 
13     @Override
14     public void signConstract() {
15         System.out.println("周杰伦去签合同");
16     }
17 
18     @Override
19     public void bookTicket() {
20         System.out.println("周杰伦去订票");
21     }
22 
23     @Override
24     public void sing() {
25         System.out.println("周杰伦去唱歌");
26     }
27 
28     @Override
29     public void collectMoney() {
30         System.out.println("周杰伦去收款");        
31     }
32 
33 }

  (3)创建代理角色的处理器

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 
 4 /**
 5  * 代理角色的处理类
 6  * jdk自带的动态代理
 7  * @author CL
 8  *
 9  */
10 public class StarHandler implements InvocationHandler {
11     private Star realStar;
12     
13     public StarHandler(Star realStar) {
14         this.realStar = realStar;
15     }
16 
17     //通过invoke方法实现对真实角色的代理访问
18     @Override
19     public Object invoke(Object proxy, Method method, Object[] args)
20             throws Throwable {
21         Object obj = null;
22         
23         System.out.print("在执行真实角色的方法之前的处理,比如-->");
24         System.out.println("面谈,签合同,订票");
25         
26         if (method.getName().equals("sing")) {
27             obj = method.invoke(realStar, args);
28         }
29         
30         System.out.print("在执行真实角色的方法之后的处理,比如-->");
31         System.out.println("收款");
32         
33         return obj;
34     }
35 
36 }

  (4)测试

 1 import java.lang.reflect.Proxy;
 2 
 3 /**
 4  * 测试JDK自带的动态代理
 5  * @author CL
 6  *
 7  */
 8 public class Client {
 9 
10     public static void main(String[] args) {
11         Star realStar = new RealStar();
12         
13         StarHandler handler = new StarHandler(realStar);
14         
15         Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class}, handler);
16         
17         proxy.sing();
18     }
19 }

  控制台输出:

在执行真实角色的方法之前的处理,比如-->面谈,签合同,订票
周杰伦去唱歌
在执行真实角色的方法之后的处理,比如-->收款

 

posted @ 2018-01-17 16:26  C3Stones  阅读(435)  评论(0编辑  收藏  举报