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的代理,如果我们下需要对火车,自行车实现相同的代理,我们又该如何实现呢?

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

  • 相关阅读:
    磁盘冗余阵列之RAID5的配置
    国际C语言混乱代码大赛优胜作品详解之“A clock in one line”
    C#数据结构_树
    C#数据结构_栈和队列
    C#数据结构_基本概念及线性表
    C#数据结构_排序
    unity之shader
    Unity之Update与FixedUpdate区别
    unity之游戏特效
    unity之加载场景
  • 原文地址:https://www.cnblogs.com/excellencesy/p/9121686.html
Copyright © 2011-2022 走看看