简介 目录 评价 推荐
  • 努力学习搬砖 2022-03-31

    设计模式——代理模式(具备面向对象的设计思维、了解多态、反射机制)

    一、基本概念及分类

        1、定义:为其他对象提供一种代理以控制对这个对象的访问(购买火车票去代售网点、找代理),代理对象起到中介作用,可去掉功能服务或增加额外服务。

        2、常见的代理模式

            (1)远程代理:为不同地理的对象提供局域网代表对象(客户端、服务器等)

                     例如:连锁店查看门店经营情况(通过远程代理可以监控各个店铺,使之能直观地了解店内信息)

            (2)虚拟代理:格局需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建

                     例如:浏览网页中的图片时以默认图片显示,当图片加载完成后再查看

            (3)智能引用代理:提供给目标对象一些额外的服务

                     例如:火车票代售处、日志处理、权限管理、事务处理...

            (4)保护代理:控制对一个对象的访问权限

                     例如:浏览网页时,普通用户只有浏览权限,当用户注册登录后,才可以进行发帖、删除、评论等操作

    二、开发中的应用场景

    三、实现方式(以智能引用代理为例)

        1、静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或者继承相同的抽象类。

            实现例子:车辆在公路上行驶,通过代理实现车辆行驶的方法,增加一个记录车辆行驶的方法

       不使用代理正常实现:

    public interface Moveable{
        void move();
    }
    public class Car implements Moveable{
        
        @Override
        public void move(){
            long starttime = System.currentTimeMillis();
               System.out.println("汽车开始行驶...");
               //实现开车
               try{
                   Thread.sleep(new Random().nextInt(1000));
                   System.out.println("汽车行驶中...");
               }catch(InterruptedException e){
                   e.printStackTrace();
               }
               long endtime = System.currentTimeMillis();
               System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");
        }
    }
    public class Client{
        public static void main(String[] args){
            Car car = new Car();
            car.move();
        }
    }

        (1)通过继承的方式实现:

    public interface Moveable{
       void move();
    }
    public class Car implements Moveable{
       
       @Override
       public void move(){
               //实现开车
               try{
                   Thread.sleep(new Random().nextInt(1000));
                   System.out.println("汽车行驶中...");
               }catch(InterruptedException e){
                   e.printStackTrace();
               }
       }
    }
    public calss Car2 extends Car{
        @Override
           public void move(){
               long starttime = System.currentTimeMillis();
               System.out.println("汽车开始行驶...");
               super.move();
               long endtime = System.currentTimeMillis();
               System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");
           }
    }
    public class Client{
       public static void main(String[] args){
           Moveable m = new Car2();
           m.move();
       }
    }

        (2)通过聚合(一个类当中调用另一个对象)的方式实现:

    public interface Moveable{
       void move();
    }
    public class Car implements Moveable{
       @Override
       public void move(){
               //实现开车
               try{
                   Thread.sleep(new Random().nextInt(1000));
                   System.out.println("汽车行驶中...");
               }catch(InterruptedException e){
                   e.printStackTrace();
               }
       }
    }
    public calss Car3 implements Moveable{
       private Car car;
       
       public Car3(Car car){
           super();
           this.car = car;
       }
       @Override
           public void move(){
               long starttime = System.currentTimeMillis();
               System.out.println("汽车开始行驶...");
               car.move();
               long endtime = System.currentTimeMillis();
               System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");
           }
    }
    public class Client{
       public static void main(String[] args){
           Car car = new Car();
           Moveable m = new Car3(car);
           m.move();
       }
    }

        

    思考:通过继承和聚合两种方式都能实现静态代理,但究竟哪种方式更好呢?

            以上是在实现对象方法move()的外层添加方法运行时间处理功能,想要增加权限管理、增加日志处理实现功能的叠加,通过两种方式示例:

        (1)通过继承方式实现(代理类会无限膨胀下去)

                先记录日志,再记录时间:需要先创建类Car4继承Car2或者Car,在move()方法前后先记录日志,再记录时间;

                先记录时间,再记录日志:需要先创建类Car5继承Car2或者Car,在move()方法前后先记录时间,再记录日志;

                先处理权限,再记录日志,再记录时间:需要先创建类Car6继承Car2或者Car,先处理权限,再记录日志,再记录时间;

                先处理权限,再记录时间,再记录日志:需要先创建类Car7继承Car2或者Car,先处理权限,再记录时间,再记录日志;

         (2)通过聚合方式实现 (代理类实现相同的接口,且代理之间相互传递、组合)

    public interface Moveable{
       void move();
    }
    public class Car implements Moveable{
       @Override
       public void move(){
               //实现开车
               try{
                   Thread.sleep(new Random().nextInt(1000));
                   System.out.println("汽车行驶中...");
               }catch(InterruptedException e){
                   e.printStackTrace();
               }
       }
    }
    public calss CarTimeProxy implements Moveable{
       private Moveable m;
       
       public CarTimeProxy (Moveable m){
           super();
           this.m = m;
       }
       @Override
           public void move(){
               long starttime = System.currentTimeMillis();
               System.out.println("汽车开始行驶...");
               m.move();
               long endtime = System.currentTimeMillis();
               System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");
           }
    }
    public calss CarLogProxy implements Moveable{   
        private Moveable m;      
        public CarLogProxy (Moveable m){       
            super();       
            this.m = m;   
        }   
        @Override       
        public void move(){           
            System.out.println("日志开始...");          
            m.move();           
            System.out.println("日志结束...");       
        }
     }
     public class Client{   
         public static void main(String[] args){       
             Car car = new Car();       
             //先记录日志,再记录时间       
             CarTimeProxy ctp = new CarTimeProxy (car);        
             CarLogProxy  clp = new CarLogProxy (ctp);              
             clp.move();            
             //先记录时间,再记录日志        
             CarLogProxy  clp = new CarLogProxy (car);           
             CarTimeProxy ctp = new CarTimeProxy (car);        
             ctp .move(); 
         }  
     }

        思考:不同的类(Car,Train)实现相同的代理(TimeProxy,LogProxy)怎样实现(如果用静态代理的聚合方式实现,每增加一个类就要新创建新类的TimeProxy,LogProxy代理类,造成类膨胀)?

        有没有一种方法:能够动态产生代理,实现对不同类、不同方法的代理——动态代理

        2、动态代理(在代理类与被代理类之间加入了实现InvocationHandler【事务处理器】类)

            (一)JDK动态代理

                Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

                (1)Interface Invocationhandler:该接口中仅定义了一个方法

                         public Object invoke(Object obj,Method method, Object[] args)

                         在实际使用中,参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。

                (2)Proxy:该类即为动态代理类

                         static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) :返回代理类的一个实例,返回后的代理类可以当做被代理类使用(可使用被代理类的在接口中声明过的方法)

            JDK动态代理代码实现:

    public interface Moveable{
      void move();
    }
    public class Car implements Moveable{
      @Override
      public void move(){
              //实现开车
              try{
                  Thread.sleep(new Random().nextInt(1000));
                  System.out.println("汽车行驶中...");
              }catch(InterruptedException e){
                  e.printStackTrace();
              }
      }
    }
    public class TimeHandler implements InvocationHandler{
       private Object target;
       public TimeHandler(Object target){
           super();
           this.target = target;
       }
       /*
       *参数:
       *proxy:被代理的对象
       *method:被代理对象的方法
       *args:方法的参数
       *返回值:
       *Object:方法的返回值
       */
       @Override
       public Object invoke(Object proxy,Method method,Object[] args) throw Throwable{
           long starttime = System.currentTimeMillis();
           System.out.println("汽车开始行驶...");
           method.invoke(target);
           long endtime = System.currentTimeMillis();
           System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");
       }
    }
    //JDK动态代理测试
    public class Test{
       public static void main(String[] args){
           Car car = new Car();
           InvocationHandler h = new TimeHandler(car);
           Class<?> cls = car.getClass();
           /*
           *参数:
           *loader:类加载器
           *interfaces:实现接口
           *h:实现处理器InvocationHandler 
           */
           Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),h);
           m.move();
       }
    }

            所谓动态代理是在运行时生成的class,该class需要实现一组interface,使用动态代理类时,必须事先InvocationHandler接口。

            JDK动态代理实现步骤:

            1、创建一个实现皆苦InvocationHandler的类,它必须事先invoke()方法;

            2、创建被代理的类及接口;

            3、调用Proxy类的静态方法,创建一个代理类;

                 static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

            4、通过代理调用方法。

            实现作业:实现Car类的多个动态代理类(记录日志、时间)

    实现作业:实现Car类的多个动态代理类(记录日志、时间)

            (二)CGLIB动态代理

            JDK动态代理与CGLIB动态代理的区别:

            JDK动态代理:

                1、只能代理实现了接口的类;

                2、没有实现接口的类不能实现JDK的动态代理。

            CGLIB动态代理:

                1、针对类来实现代理的;

                2、对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

        CGLIB动态代理实现代码示例(导包:cglib-nodep-2.2.jar):

    public class Train{
       public void move(){
           System.out.println("火车行驶中......")
       }
    }
    public class CglibProxy implements MethodInterceptor{
       private Enhancer enhancer = new Enhancer();
       public Object getProxy(Class clazz){
           //设置创建子类的类
           enhancer.setSuperclass(clazz);
           enhancer.setCallback(this);
           return enhancer.create();
       }
       /*拦截所有目标类方法的调用
       *参数:
       *obj:目标类的实例
       *m:目标方法的反射对象
       *args:方法的参数
       *proxy:代理类的实例
       */
       @Override
       public Object intercept(Object obj, Method m, Object[] args,MethodProxy proxy) throw Throwable{
           System.out.println("日志开始...");
           //代理类调用父类的方法
           proxy.invoke(obj,args);
           System.out.println("日志结束...");
           return null;
       }
    }
    public class Test{
       public static void main(String[] args){
           CglibProxy proxy = new CglibProxy();
           Train t = proxy.getProxy(Train.class);
           t.move();
      }
    }

    四、理解JDK动态代理的实现

     动态代理实现思路(实现功能:通过Proxy的newProxyInstance返回代理对象)

        1、声明一段源码(动态产生代理)

        2、编译源码(JDKCompiler API),产生新的类(代理类)

        3、将这个类load到内存当中,产生一个新的对象(代理对象)

        4、return代理对象

    代码实现:

    public class Proxy{
       public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
         String rt = "\r\t";
         String methodStr = "";
         for(Method m : infce.getMethods()){
            methodStr +="@Override" + rt +
           "public void "+m.getName()+"(){" + rt +
               /*
               "long starttime = System.currentTimeMillis();" + rt +
               "System.out.println("汽车开始行驶...");" + rt +
               "m."+m.getName()+"();" + rt +
               "long endtime = System.currentTimeMillis();" + rt +
               "System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");" + rt +
               */
               "try{" + rt +
                   "Method md =" + infce.getName() +".class.getMethod(\""+m.getName()+"\");" + rt +
                   "h.invoke(this,md);" + rt +
               "}catch(Exceotipn e){" + rt +
                   "e.printStackTrace();" + rt +
               "}" + rt +
           "}";
       }
       String str =
       "public calss $Proxy0 implements" + infce.getName()+ "{" + rt +
            
            "public $Proxy0 (InvocationHandler h){" + rt +
             "super();" + rt +
             "this.h = h;" + rt +
            "}" + rt +
            " private InvocationHandler h;" + rt +
            methodStr  + rt +
           "}";
           //String filename = System.getProperty("user.dir");
           //System.out.println(filename);//C:/Proxy        
           //产生代理类的Java文件        
           String filename = System.getProperty("user.dir")+"/bin/com/imooc/proxy/$Proxy0.java";
           File file = new File(filename);        
           //FileUtils(commons-io的jar包下的类)        
           FileUtils.writeStringToFile(file,str);        
           //编译        
           //拿到编译器        
           JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();        
           //文件管理者        
           StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null,null,null); 
           //获取文件        
           Iterable units = fileMgr.getJavaFileObjects(filename);        
           //编译任务        
           CompilationTask t = compiler.getTask(null,fileMgr,null,null,null,units);        
           //进行编译        
           t.call();        
           fileMgr.close();        
           //load到内存        
           ClassLoader cl = ClassLoader.getSystemClassLoader();       
            Class c = cl.loadClass("$Proxy0");        
            Constructor ctr = c.getConstructor(InvocationHandler.class);        
            System.out.println(c.getName());//$Proxy0        
            return ctr.newInstance(h);  
        }
    }
    /*测试类*/
    public class Client{    
       public static void main(String[] args) throws Exception{
           Car car = new Car();
           InvocationHandler h = new TimeHandler(car);
           Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class,h);        
           m.move();
       }
    }
    public class Test{
       public static void main(String[] args){
           Car car = new Car();       
           InvocationHandler h = new TimeHandler(car);       
           Class<?> cls = car.getClass();       
           /*       
           *参数:       
           *loader:类加载器       
           *interfaces:实现接口       
           *h:实现处理器InvocationHandler        
           */       
           Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),h);       
           System.out.println("代理类名字" + m.getClass().getName());//代理类名字$Proxy0       
           m.move();   
       }
    }
    public class InvocationHandler{
       public void invoke(Object o,Method m);
    }
    public class TimeHandler implements InvocationHandler{
       private O bject target;
       public TimeHandler(Object target){
           this.target = target;
       }
       @Override
       public void invoke(Object o,Method m){
           try{
               long starttime = System.currentTimeMillis();
               System.out.println("汽车开始行驶...");
               m.invoke(target);
               long endtime = System.currentTimeMillis();
               System.out.println("汽车结束行驶...汽车行驶时间:"+(endtime - starttime) + "毫秒");
           }catch(Exception e){
               e.printStackTrace();
           }
       }
    }

    五、总结

    0赞 · 0采集
  • 慕粉42788080 2020-03-09

    222222222222222222222222222222222222222

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    智能引用代理

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    保护代理应用

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    虚拟代理例子

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    虚拟代理概念

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    例 子 例 子

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    远 程 代 理

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    常用代理模式

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    代理模式基本概念

    截图
    0赞 · 0采集
  • ciicjsb 2020-02-20

    代理模式定义

    截图
    0赞 · 0采集
  • 慕容0032301 2019-10-16
    代理模式:为其他对象提供代理,以控制对这个对象的访问
    截图
    0赞 · 1采集
  • 大鹏111 2019-07-29

    代理模式概念:为其他对象提供一种代理以控制对这个对象的访问,代理对象起到中介作用。

    常见的几种代理模式:

    1、远程代理:代理模式的经典应用,类似于客户端、服务器的模式,为不同地理的对象提供局域网代表对象。

    2、保护代理:控制对一个对象的访问权限。

    3、智能代理:提供目标对象额外的一些服务。

    4、虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建。

    0赞 · 3采集
  • GT9456 2019-06-25

    代理模式:为其他对象提供一种代理,以控制对这个对象的访问。

    0赞 · 0采集
  • Uestc_L 2019-06-23

    概念及分类:为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。

    代理模式的分类:

    远程代理:为不同地理的对象,提供局域网代表对象。

    虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建。

    保护代理:控制对一个物品的访问权限。

    智能引用代理:额外其他的服务


    0赞 · 0采集
  • 慕仰mooc 2019-05-06

    代理模式 1、概念:为其他对象提供一种代理,以控制对这个对象的访问(例如火车站代售处)。代理对象起到中介作用,可去掉功能服务或增加额外的服务。 2、分类:a、远程代理---为不同地理的对象提供局域网代表对象。(类似于客户端和服务器端) b、虚拟代理---根据需要将资源消耗很大的对象进行延迟,真正需要的时候才进行创建。(网页中 图片的加载,先用一张虚拟的图片进行显示,等图片加载完成后再进行显示) c 、保护代理---控制用户的访问权限。(发帖功能) d、智能应用代理---提供对目标对象一些额外的服务。(火车站)

    0赞 · 0采集
  • 望生帝 2019-03-18

    几种场景的代理模式:

    远程代理:为不同地理的对象,提供局域网代表对象。

    虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建。

    保护代理:控制对一个物品的访问权限。

    智能引用代理:额外其他的服务


    0赞 · 0采集
  • 望生帝 2019-03-18

    设计模式之代理模式

    概念及分类:为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。

    0赞 · 0采集
  • qq_啊_37 2019-03-15

    1、什么是代理模式?

      为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,课去掉功能服务或增加额外的服务。

    2、代理模式种类

    (1)远程代理

    (2)虚拟代理

    (3)保护代理

    (4)智能引用代理

    0赞 · 0采集
  • 魔光佛影 2019-03-14

    代理模式的定义:为其他对象提供一种代理以控制对这个类的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务

    截图
    0赞 · 0采集
  • xyx8888 2019-02-13

    智能引用代理定义

    截图
    0赞 · 1采集
  • xyx8888 2019-02-13

    保护代理定义

    截图
    0赞 · 1采集
  • xyx8888 2019-02-13

    虚拟代理定义

    截图
    0赞 · 1采集
  • xyx8888 2019-02-13

    代理模式定义

    截图
    0赞 · 1采集
  • xyx8888 2018-12-18

    设计模式--代理模式

    基本概念: 为其他对象提供代理以控制这个对象的访问;代理对象起到中介作用,可删除或者增加额外服务

    截图
    0赞 · 0采集
  • weixin_慕村030779 2018-11-25

    一、代理模式概念及分类

    1、概念

    为其它对象提供一种代理以控制对这个对象的访问

    代理对象起到中介作用,可去掉功能服务或增加额外的服务

    2、常见的几种代理模式

         a、远程代理

         b、虚拟代理

         c、保护代理

         d、智能引用代理

    0赞 · 0采集
  • 谁的危笑 2018-07-02

    代理模式的分类: 

    远程代理模式:为不同地理的对象提供局域网代表对象(例子:通过远程代理可以监控各个店铺,使之可以直观的了解店里的情况)

     虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建 (类似于新闻网站加载时,图片加载不出来先用一张空的图片代替)

    保护代理:控制用户的访问权限 

    智能引用代理:提供对目标对象提供额外的服务(火车票代售处)

    0赞 · 0采集
  • qq_王杰_3 2018-06-02

    @设计模式---代理模式简介与分类

    代理模式:
        为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。

    代理模式的分类:
        1.远程代理模式:为不同地理的对象提供局域网代表对象(监控各个店铺
        2.虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建(图片的延时加载)
        3.保护代理:控制用户的访问权限(网站页面的访问权限)
        4.智能引用代理:提供对目标对象提供额外的服务(火车票代售处


    0赞 · 0采集
  • BirdOfV 2018-05-31

    @设计模式---代理模式简介与分类

    代理模式:
        为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。

    代理模式的分类:
        1.远程代理模式:为不同地理的对象提供局域网代表对象(监控各个店铺
        2.虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建(图片的延时加载)
        3.保护代理:控制用户的访问权限(网站页面的访问权限)
        4.智能引用代理:提供对目标对象提供额外的服务(火车票代售处

    0赞 · 1采集
  • cherryljr 2018-05-06

    代理模式的分类:

    1.远程代理(为不同区域的对象提供一个局域网对象,如有多个分店可以用一个监视器来监视各个分店的情况)

    2.虚拟代理(如 有一张图片还没被加载下来的话可以用另外一张默认图片来代替这个图片,加载好以后就可以把这个图片加载进来)

    3.保护代理(进行一些权限的设置)

    4.智能代理


    0赞 · 1采集
数据加载中...
开始学习 免费