美文网首页
设计模式之代理模式一

设计模式之代理模式一

作者: 小白小白啦 | 来源:发表于2018-08-05 14:43 被阅读9次

    本文主要参考慕课网视频学习,在此记录一下,个人感觉讲的非常棒。随着对spring框架的了解,代理模式在其中发乎了很大作用,要想更好的理解spring的核心之一AOP需要对代理模式有一些了解。
    代理模式我个人理解就是通过一个对象A去访问另外一个对象B,而不是直接去访问B,为什么不直接访问B呢?因为有时候我们需要在访问B之前做一些代码逻辑判断,比如spring框架中的面向切面编程,我需要判断用户是否登录才能访问a,b,c,d这四个函数,就可以通过切面实现,并且没有破坏a,b,c,d函数的代码,只需要在每一个函数上面加一个注解或者通过正则表达式进行判断。

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

    静态代理

    以汽车行驶,记录汽车行驶时间为例子进行讲解,首先创建一个Movable接口。

    public interface Moveable {
        void move();
    }
    

    创建一个Car实现类

    import java.util.Random;
    
    /**
     * Create by fengguofei
     * Date: 2018/8/5
     * Time: 13:39
     */
    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) + "毫秒!");
        }
    }
    

    创建一个测试Client类

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

    输出

    汽车开始行驶。。。
    汽车行驶中。。。
    汽车结束行驶。。。 汽车行驶时间:621毫秒!
    

    可以看到实现了汽车行驶时间的记录
    通过继承实现代理
    创建一个Car2继承Car,然后删除Car里面有关计时的代码,放到Car2里面。
    修改Car类代码

    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) + "毫秒!");
        }
    }
    

    创建Car2

    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("汽车结束行驶。。。 汽车行驶时间:" + (endtime - starttime) + "毫秒!");
        }
    }
    

    修改Client类代码

    public class Client {
        public static void main(String[] args) {
    //        Car car = new Car();
    //        car.move();
    
            Moveable m = new Car2();
            m.move();
        }
    }
    

    输出

    汽车开始行驶。。。
    汽车行驶中。。。
    汽车结束行驶。。。 汽车行驶时间:906毫秒!
    

    通过Car2里面的super.move实现了对Car的代理。
    使用聚合方式
    创建Car3

    public class 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) + "毫秒!");;
        }
    }
    

    修改Client类代码

    public class Client {
    
        public static void main(String[] args) {
    //        Car car = new Car();
    //        car.move();
    
              //使用集成方式
    //        Moveable m = new Car2();
    //        m.move();
    
            //使用聚合方式实现
            Car car = new Car();
            Moveable m = new Car3(car);
            m.move();
        }
    }
    

    输出

    汽车开始行驶。。。
    汽车行驶中。。。
    汽车结束行驶。。。 汽车行驶时间:652毫秒!
    

    聚合方式我感觉就是两个类实现同一个接口,Car类实现move功能,然后通过构造函数把Car类注入到Car3中,在调用Car类move时做一些处理,从而实现了代理功能。

    继承方式和聚合方式那个好一点呢?答案是聚合方式

    功能叠加.png
    如果我们需要在Move上实现时间处理、权限、日志等功能。比如需要实现先输出时间,再输出日志就需要创建一个Car4继承Car,如果我想先输出日志,再输出时间呢?就需要在创建一个Car5继承Car,只是顺序颠倒一下,就需要在创建一个,如果功能多的话,就需要创建很多类,太麻烦了。使用聚合就不会有这种问题出现。
    直接上代码,看了就懂了。
    创建一个时间代理类CarTimeProxy
    public class 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) + "毫秒!");;
        }
    }
    

    创建一个日志代理类CarLogProxy

    public class 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("日志结束。。。");;
        }
    }
    

    修改Client代码

    public class Client {
    
        public static void main(String[] args) {
    //        Car car = new Car();
    //        car.move();
    
              //使用集成方式
    //        Moveable m = new Car2();
    //        m.move();
    
            //使用聚合方式实现
    //        Car car = new Car();
    //        Moveable m = new Car3(car);
    //        m.move();
    
            Car car = new Car();
            CarTimeProxy ctp = new CarTimeProxy(car);
            CarLogProxy clp = new CarLogProxy(ctp);
            clp.move();
        }
    }
    

    输出

    日志开始。。。
    汽车开始行驶。。。
    汽车行驶中。。。
    汽车结束行驶。。。 汽车行驶时间:843毫秒!
    日志结束。。。
    

    上面是先输出日志,再输出时间。如果我想先输出时间,再输出日志呢?
    只需要修改一下顺序即可

       Car car = new Car();
       CarLogProxy clp = new CarLogProxy(car);
       CarTimeProxy ctp = new CarTimeProxy(clp);
       ctp.move();
    

    输出

    汽车开始行驶。。。
    日志开始。。。
    汽车行驶中。。。
    日志结束。。。
    汽车结束行驶。。。 汽车行驶时间:510毫秒!
    

    在后面一篇文章进行JDK动态代理和cglib动态代理的讲解。
    设计模式之代理模式二

    相关文章

      网友评论

          本文标题:设计模式之代理模式一

          本文链接:https://www.haomeiwen.com/subject/parbvftx.html