zoukankan      html  css  js  c++  java
  • 设计模式之代理模式

    设计模式之代理模式
    1. 代理模式具体介绍

      1. 代理模式:为被代理对象提供一个提升,以控制对这个对象的访问。即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增加额外的功能操作,即扩展目标对象的功能

      2. 被代替的对象可以是远程对象、创建开销大的对象或者需要进行安全控制的对象

      3. 代理模式有三种不同的类型:静态代理、动态代理(JDK代理)、Cglib代理(特点可以在内存中动态的创建对象,而不需要实现接口,属于动态代理范畴)

      4. 代理模式类图

    2. 静态代理模式基本介绍

      1. 静态代理在使用时,需要定义接口或者父类,被代理的对象(即目标对象)与代理对象一起实现相同的接口或者继承相同的父类

      2. 案例

        1. 要求

          1. 定义一个接口IteacherDao

          2. 目标对象TeacherDao实现接口ITeacherDao

          3. 使用静态代理方式,就需要在代理对象TeacherDaoProxy中也实现接口IteacherDao

          4. 调用的时候通过调用代理对象的方法来调用目标对象

          5. 注意:代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法

        2. 静态代理类图

        3. 代码实现

          //接口,代理对象和被代理对象都需要实现
          public interface ITeacherDao{
             public abstract void teach();
          }

          //创建被代理对象类
          public class TeacherDao implements ITeacherDao{
             @Override
             public void teach(){
                 System.out.println("开始上课了")
            }
          }

          //代理对象
          public class TeacherDaoProxy implements ITeacherDao{
             private ITeacherDao target;
             public TeacherDaoProxy(ITeacherDao target){
                 this.target=target ;
            }
             
              @Override
             public void teach(){
                 System.out.println("代理开始,完成某些操作 ");
                 target.teach();
                  System.out.println("提交 ");
            }
          }

          public class Client{
             public static void main(String[] ags){
                 //创建目标对象,即被代理的对象
                TeacherDao teacherDao = new TeacherDao();
                 //创建代理对象.同时把被代理对象传给代理对象
                TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
                //通过代理对象调用被代理对象的方法
                 teacherDaoProxy.teach();
                 
            }
          }

           

        4. 代理对象的优缺点

          1. 优点:在不修改对象功能的前提下,能通过代理对象对目标功能扩展

          2. 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

          3. 一旦接口增加方法,目标对象与代理对象都需要维护

      3. 动态代理

        1. 介绍

          1. 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能使用动态代理

          2. 代理对象的生成,是利用JDK的API,动态的在内部中构建代理对象

          3. 动态代理对象也叫作:JDK代理、接口代理

        2. JDK中生成代理对象的API

          1. 代理类所在的包:java.lang.reflect.Proxy

          2. JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是

            static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,Invocationhandler h)

             

        3. 类图

        4. 代码实现

          //接口,代理对象和被代理对象都需要实现
          public interface ITeacherDao{
             public abstract void teach();
              public abstract void sayHello();
          }

          //创建被代理对象类
          public class TeacherDao implements ITeacherDao{
             @Override
             public void teach(){
                 System.out.println("开始上课了")
            }
              @Override
             public void teach(String name){
                 System.out.println("hello"+name)
            }
          }

          //代理工厂
          public class ProxyFactory{
             //维护一个目标对象
             private Object target;
             public ProxyFactory( Object target){
                 this.target=target;
            }
             
             //给目标对象生成一个代理对象
             public Object getProxyInstance(){
                 //说明
                 //1.ClassLoader loader:指定当当前目标对象使用的类加载器,获取加载器的方法固定
                 //2.Claaa<?>[] interfaces:目标对象实现的接口类型,使用泛型方式确认类型
                 //3.InvocationHandler h:事件处理,执行目标对象的方法时,会去触发事件处理器的方法(会把当前目标对象执行的方法作为参数传入)
                 return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterface(),new InvocationHandler(){
                     @Override
                     public Object invoke(Object proxy,Method method,Object[] args){
                         System.out.println("JKD代理开始");
                        Object invoke= method.invoke(target,args);
                         return invoke;
                    }
                });
            }
          }


          public class Client{
             public static void main(String[] ags){
                 //创建目标对象,即被代理的对象
                ITeacherDao target = new TeacherDao();
                 //给目标对象创建代理对象
                ITeacherDao proxyInstance= (ITeacherDao) new ProxyFactory(target).getProxyInstance();
                 //下面展示的结果就是内存中动态生成的代理对象
                System.out.println("proxyInstance="+proxyInstance.getClass());
                 //通过代理对象调用目标对象的方
                 proxyInstance.teach();
                 
            }
          }

           

        5. 优缺点

      4. Cglib代理

        1. 基本介绍

          1. 静态代理模式和JDK代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可以使用目标对象子类来实现代理-这就是Cglib代理

          2. Cglib代理也叫作子类代理,他是在内存中构建一个子类对象从而实现对目标对象功能的扩展

          3. Cglib是一个强大的高性能的代码生成包,他可以在运行期间扩展java类与实现java接口。它广泛的被许多AOP框架使用,例如Spring AOP,实现方法拦截

          4. 在AOP 编程中如何选择代理模式

            1. 目标对象需要实现接口,使用JDK代理

            2. 目标对象不需要实现接口,使用Cglib代理

          5. Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类

        2. 类图

        3. 代码

          //注意需要引包

          //创建被代理对象类
          public class TeacherDao{
             
             public void teach(){
                 System.out.println("开始上课了,我是Cglib不需要实现接口");
            }
          }

          public class ProxyFactory implements MethodInterceptor{
             private Object target;
             public ProxyFactory(Object target){
                 this.target = target;
            }
             
             //返回一个代理对象,是target的代理对象
             public Object getProxyInstance(){
                 //1.创建一个工具类
                 Enhancer enhancer= new Enhancer();
                 //2.设置父类
                 enhancer.setSuperClass(target.getClass());
                 //3.设置回调函数
                 enhancer.setCallback(this);
                 //4.创建子类对象,即代理对象
                 return enhancer.create();
            }
             //会调用目标对象的相关方法
             @Override
             public Object intercept(Object args,Method arg1,Object[] args2,Methodproxy arg3) throws Throwable{
                 System.out.println("Cglib代理模式开始");
                Ibject returnVal= args1.invoke(target,args);
                 System.out.println("Cglib代理模式提交");
                 return returnVal;
            }
             
          }

          public class Client{
             public static void main(String[] args){
                 TeacherDao target=new TeacherDao();
                 //获取代理对象
                 TeacherDao teacherDao =(TeacherDao)new ProxyFactory(target).getProxyInstance();
                 //执行代理对象的方法,触发intercept方法 从而实现对目标对象的调用
                 teacherDao.teach();
            }
          }

           

  • 相关阅读:
    ASE19团队项目 beta阶段 model组 scrum report list
    ASE19团队项目 beta阶段 model组 scrum7 记录
    ASE19团队项目 beta阶段 model组 scrum6 记录
    ASE19团队项目 beta阶段 model组 scrum5 记录
    ASE19团队项目 beta阶段 model组 scrum4 记录
    ASE19团队项目 beta阶段 model组 scrum3 记录
    ASE19团队项目 beta阶段 model组 scrum2 记录
    ASE19团队项目 beta阶段 model组 scrum1 记录
    【ASE模型组】Hint::neural 模型与case study
    【ASE高级软件工程】第二次结对作业
  • 原文地址:https://www.cnblogs.com/juddy/p/15013480.html
Copyright © 2011-2022 走看看