• 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 }

      控制台输出:

    在执行真实角色的方法之前的处理,比如-->面谈,签合同,订票
    周杰伦去唱歌
    在执行真实角色的方法之后的处理,比如-->收款
  • 相关阅读:
    Java 在方法和作用域内的内部类
    java 内部类和向上转型
    java 内部类使用 .this 和 .new
    java innerclasses(内部类)
    Java过滤器与SpringMVC拦截器之间的关系与区别
    Maven异常:Could not find artifact
    soapUI测试webservice(参数为xml格式的处理方式)
    maven仓库加载本地包依赖
    spring data jpa的学习总结
    Java 中常用缓存Cache机制的实现
  • 原文地址:https://www.cnblogs.com/cao-lei/p/8303613.html
Copyright © 2020-2023  润新知