zoukankan      html  css  js  c++  java
  • 代理模式(Proxy)--静态代理

    1,代理模式的概念

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

    2,代理模式的分类

    (1)远程代理:类似于客户机服务器模式

      为不同地址空间的对象提供局域网代表对象

        举例说明:通过远程代理监控各个店铺

      

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

        举例说明:当对一个网页进行记载的时候,会先使用一张默认的图片代替要加载的图片,将文字等其他信息和默认的图片一起加载出来,在慢慢加载指定的图片。

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

        举例说明:在浏览某个网站的时候,未登录状态,只能浏览网站,只有在登陆后才可以发帖。

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

        举例说明:火车票代购处,不仅提供了销售火车票的功能,还提供了电话预约的功能。

    3,智能引用代理---静态代理:

    模拟场景:车行驶的路上,代理添加新功能:记录行驶的时间

    (1)在不使用代理的情况下:

    S1:编写行驶接口类Moveable

    package com.songyan.proxy;
    
    public interface Moveable {
    void move();
    }

    S2:编写小汽车类实现Moveable接口

    并实现Moveable中定义的行驶方法(move())

    在行驶方法中获取运行开始时,运行结束时的时间,做差获取运行的时间,由于程序运行太快,使用Thread的sleep()休眠1秒

    package com.songyan.proxy;
    
    import java.util.Random;
    
    public class Car implements Moveable {
        public void move() {
            long startTime=System.currentTimeMillis();
            System.out.println("汽车行驶的开始时间:"+startTime);
            
            //实现开车
            try {
                Thread.sleep(new Random().nextInt(1000));
                System.out.println("汽车行驶中");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            long endTime=System.currentTimeMillis();
            System.out.println("骑车行驶的终止时间:"+endTime);
            System.out.println("汽车行驶时间共计:"+(endTime-startTime)+"毫秒~");
            
        }
    
    }

    S3:编写测试类,是小汽车行驶

    package com.songyan.proxy;
    
    public class Client {
        public static void main(String[] args) {
            Car car= new Car();
            car.move();
        }
        
    }

    S4:运行结果

    (2)代理实现记录汽车行驶的时间---继承

    S1:新建Car2继承Car

    S2:重写move方法

    S3:将car中的记录时间的部分抽取出来,只留下汽车行驶的部分

    package com.songyan.proxy;
    /**
     * 
     * @author sy
     *通过继承Car2实现对Car的代理
     */
    public class Car2 extends Car{
        @Override
        public void move() {
            long startTime=System.currentTimeMillis();
            System.out.println("开始行驶~~~~");
            
            super.move();
            
    
            long endTime=System.currentTimeMillis();
            System.out.println("行驶结束~~~~~~~~~~");
            System.out.println("汽车行驶时间:"+(endTime-startTime)+"毫秒~");
        }
    
    }

     

     

    package com.songyan.proxy;
    
    import java.util.Random;
    
    public class Car implements Moveable {
        public void move() {
            System.out.println("移动~~~~~~~~~~~~");
            try {
                Thread.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

     

    S4:编写测试类测试

    package com.songyan.proxy;
    
    public class Client {
    public static void main(String[] args) {
        /*Car car=new Car();
        car.move();*/
        Moveable car2=new Car2();
        car2.move();
    }
    }

     

     输出结果

    (3)代理实现记录汽车行驶的时间---聚合

    S1:编写Car3实现Moveable接口

    S2:声明一个Car类型的变量

    S3:并通过构造函数进行初始化

    S4:重写move方法,调用car的move()在写逻辑代码。

    package com.songyan.proxy;
    /**
     * 
     * @author sy
     * 通过聚合的方式实现代理
     */
    public class Car3 implements Moveable{
        private Car car;
        /**
         * 聚合:一个类当中
         */
        public void move() {
            //计时开始
            long startTime=System.currentTimeMillis();
            System.out.println("开始行驶~~~~");
            
            //调用car的move方法
            car.move();
            
            //计时结束
            long endTime=System.currentTimeMillis();
            System.out.println("行驶结束~~~~~~~~~~");
            System.out.println("汽车行驶时间:"+(endTime-startTime)+"毫秒~");        
        }
        
        /**
         * 通过构造函数将car传进来
         * @param car
         */
        Car3(Car car)
        {
            super();
            this.car=car;
        }
    
    }

     

     

    思考:以上是两种实现代理的方式,哪一种更好呢?

     

    功能拓展:上面的代理中知识拓展了记录行驶时间的功能,如果需要实现功能叠加,两种方式有该如何实现?

    (1)继承的方式

    先记录日志在记录行驶时间:需要编写Car3继承Car.

    先记录行驶时间,在记录日志:又需要编写Car4继承Car

    不难看出继承的方式代码的可重用性不高

    (2)聚合的方式(可以很好的解决上述问题)

    S1:编写实现记录时间的代理类

    package com.songyan.proxy;
    /**
     * 记录时间的代理类
     * @author sy
     *
     */
    public class CarTimeProxy implements Moveable
    {
        private Moveable m;
        public void move() {
            System.out.println("时间记录开始~~");
            m.move();
            System.out.println("时间记录结束~~");
            
        }
        public CarTimeProxy(Moveable m)
        {
            this.m=m;
        }
    }

     

    S2:编写记录日志的代理类

    package com.songyan.proxy;
    /**
     * 就日志的代理类
     * @author sy
     *
     */
    public class CarLogProxy implements Moveable{
        private Moveable m;
        public void move() {
            System.out.println("log开始~~~~");
            m.move();
            System.out.println("log结束~~~~~~");
        }
        public CarLogProxy(Moveable m)
        {
            this.m=m;
        }
    
    }

     

    S3:编写测试类(1)先记录日志在记录时间

    package com.songyan.proxy;
    /**
     * 代理组合测试类
     * @author sy
     * 要求代理:先记录日志,在记录时间
     */
    public class CarTest {
    public static void main(String[] args) {
        Moveable m=new Car();
        Moveable time=new CarTimeProxy(m);
        Moveable log=new CarLogProxy(time);
        log.move();
    }
    }

     

    运行结果:

     

     S4:编写测试类2(先记录时间在记录日志)

    不行需要重新写代理类

    只需要在调用的时候调整顺序即可

    package com.songyan.proxy;
    /**
     * 代理组合测试类
     * @author sy
     * 要求代理:先记录时间,在记录日志
     */
    public class CarTest {
    public static void main(String[] args) {
        Moveable m=new Car();
        Moveable log=new CarLogProxy(m);
        Moveable time=new CarTimeProxy(log);
        time.move();
    }
    }

     

     输出结果:

    由上可以看出:聚合要比继承更好用。

    思考:我们上面实现的都是对Car的代理,如果我们下需要对火车,自行车实现相同的代理,我们又该如何实现呢?

    这里就需要用到动态代理技术了:具体请点击此处查看另一篇博客。

  • 相关阅读:
    sublime开启vim模式
    git命令行界面
    搬进Github
    【POJ 2886】Who Gets the Most Candies?
    【UVA 1451】Average
    【CodeForces 625A】Guest From the Past
    【ZOJ 3480】Duck Typing
    【POJ 3320】Jessica's Reading Problemc(尺取法)
    【HDU 1445】Ride to School
    【HDU 5578】Friendship of Frog
  • 原文地址:https://www.cnblogs.com/excellencesy/p/9121686.html
Copyright © 2011-2022 走看看