JavaSE进阶系列(十三)、代理模式

十三、代理模式

13.1 代理的概述

  • 代理模式的作用

    为其他对象提供一种代理以控制对目标对象的访问。某些情况下客户不想或不能直接引用另一个对象,而代理对象可在客户端目标对象间起到中介作用

  • 代理模式一般涉及到的角色

  • 抽象角色:真实对象和代理对象的共同接口;

  • 真实角色:真实对象,最终要引用的对象;

  • 代理角色:

    1. 内部含有对真实对象的引用,从而可以操作真实对象;
    2. 提供与真实对象相同的接口以便在任何时刻代替真实对象;
    3. 可在执行真实对象操作前后附加其他操作,相当于对真实对象进行封装。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FyIek5J9-1616892929242)(C:\Users\wang’bo’shi\AppData\Roaming\Typora\typora-user-images\image-20210325100832068.png)]

    小贴士:

    必须明确一个动态代理类可适用多个抽象角色和真实角色!

  • 代理模式的分类

  • ## (1).静态代理

    优点:不需要修改目标对象就实现了功能的增加。

    缺点:真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。如果事先并不知道真实角色则无法使用;

    一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀。

静态代理的是演示:

  1. 抽象角色

    /**
     * 抽象角色(USB接口)
     */
    public interface USB {
        /**
         * 启动功能
         */
        void start();
    
        /**
         * 工作
         */
        void service();
    
        /**
         * 测试电脑CPU当前温度
         */
        int hotSize();
    
    }
    
  2. 真实角色

    /**
     * 真实角色(键盘实现类)
     */
    public class KeyBord implements USB {
    
        @Override
        public void start() {
            System.out.println("键盘正在插入电脑中……");
        }
    
        @Override
        public void service() {
            System.out.println("键盘正在工作中……");
        }
    
        @Override
        public int hotSize() {
            return 50;
        }
    }
    
  3. 代理角色

    /**
     * 静态代理角色(同真实角色实现类要实现USB接口)
    

/
public class UsbProxy implements USB {
/
*
* 真实角色
*/
KeyBord keyBord = new KeyBord();

   @Override
   public void start() {
       System.out.println("日志:调用start函数前置通知!");
       keyBord.start();
       System.out.println("日志:调用start函数后置通知!");
   }

   @Override
   public void service() {
       System.out.println("日志:调用service函数前置通知!");
       keyBord.service();
       System.out.println("日志:调用service函数前置通知!");
   }

   @Override
   public int hotSize() {
       System.out.println("日志:正在检测电脑温度中……");
       int i = keyBord.hotSize();
       if(i>=70){
           System.out.println("电脑温度过高!");
           return 0;
       }
       System.out.println("电脑温度正常!");
       return 1;
   }

}


4. 测试类

```java
public class Test {
    public static void main(String[] args) {

        UsbProxy usbProxy = new UsbProxy();
        usbProxy.start();
        System.out.println("-------------------");
        usbProxy.service();
        System.out.println("-------------------");
        System.out.println("CPU当前温度:" + usbProxy.hotSize() + "摄氏度!");

    }
}

运行结果:
/**
     * 日志:调用start函数前置通知!
     * 键盘正在插入电脑中……
     * 日志:调用start函数后置通知!
     * -------------------
     * 日志:调用service函数前置通知!
     * 键盘正在工作中……
     * 日志:调用service函数前置通知!
     * -------------------
     * 日志:正在检测电脑温度中……
     * 电脑温度正常!
     * CPU当前温度:50摄氏度!
     */
  • ## (2).动态代理
  1. Java动态代理类位于java.lang.reflect包下,主要涉及到两个类:InvocationHandler接口和

    Proxy类;

  2. InvocationHandler接口仅定义了一个方法:

public object invoke(Object obj,Method method, Object[] args){
  //obj一般是指代理类
  //method是被代理的方法
  //args为该方法的参数数组	
  //这个抽象方法在代理类中动态实现
}
  1. Proxy类即为动态代理类,主要方法包括:
protected Proxy(InvocationHandler h){
  //构造函数,用于给内部的h赋值
} 

static Object newProxyInstance(ClassLoader loader, Class[ ] interfaces, InvocationHandler h) {
  //返回代理类的一个实例
  //loader是类装载器
  //interfaces是真实类所拥有的全部接口的数组
}

static Class getProxyClass (ClassLoader loader, Class[] interfaces) {
  //获得一个代理类
}

动态代理的演示:

  1. 创建一个实现接口InvocationHandler的类;
  2. 在invoke方法内通过反射调用真实对象的方法,并添加附加操作;
  3. 创建被代理的类以及接口;
  4. 通过Proxy类的newProxyInstance() 创建一个代理;
  5. 必须传入一个InvocationHandler对象;
  6. 通过代理调用方法。

  1. 抽象角色

    /**
     * 抽象角色
     */
    public interface USB {
        /**
         * 启动功能
         */
        void start();
        /**
         * 工作
         */
        void service();
        /**
         * 测试电脑CPU当前温度
         */
        int hotSize();
    
        int lenth(int num);
    }
    
  2. 真实角色

    /**
     * 真实角色
     */
    public class Mouse implements USB {
        @Override
        public void start() {
            System.out.println("鼠标正在插入电脑中……");
        }
        @Override
        public void service() {
            System.out.println("鼠标正在工作中……");
        }
        @Override
        public int hotSize() {
            System.out.println("鼠标温度");
            return 50;
        }
        @Override
        public int lenth(int num) {
            return num;
        }
    }
    
  3. 动态代理角色—注意!!!(此类不是动态代理类)

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    /**
     * 动态代理角色(此类不是动态代理类,getProxy()方法返回中的newProxyInstance()才是动态代理对象,运行期间动态生成)
     */
    public class LogHandler implements InvocationHandler {
    
        /**
         * 要代理的真实角色(未知)
         */
        Object target;
    
        public LogHandler(){
        }
    
        /**
         * 要传入的真实角色
         * @param target
         */
        public LogHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("目标对象:" + target.getClass());
            System.out.println("目标对象-方法:" + method.getName());
            System.out.println("目标对象-参数:" + Arrays.toString(args));
            Object result = method.invoke(target,args);
            System.out.println("目标对象返回结果:" + result);
            return result;
        }
    
        /**
         * 获取动态代理的方法(JDK内部帮我们获取目标对象的各种信息,并负责自动调用……)
         *  getClass().getClassLoader()---类加载器
         *  getClassLoader(),getClass().getInterfaces()---类实现的接口
         *  this---指的是执行该getProxy()方法时,加载本代理类中的invoke()方法
         * @return
         */
        public Object getProxy(){
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        }
    }
    
  4. 测试类

    public class Test {
        public static void main(String[] args) {
        Mouse mouse = new Mouse();
           LogHandler logHandler = new LogHandler(mouse);
           USB usb = (USB)logHandler.getProxy();
           usb.start();
           usb.lenth(11111);
        }
    
      运行结果:
        /**
         * 目标对象:class com.wbs.proxy2.Mouse
         * 目标对象-方法:start
         * 目标对象-参数:null
         * 鼠标正在插入电脑中……
         * 目标对象返回结果:null
         * 目标对象:class com.wbs.proxy2.Mouse
         * 目标对象-方法:lenth
         * 目标对象-参数:[11111]
         * 目标对象返回结果:11111
         */
    }
    
    

小贴士:

LogHandler类不是动态代理类!!

newProxyInstance()方法返回的才是动态代理对象,是在运行时动态创建的!

13.2 两种代理模式的区别

  • 静态代理类确实存在,动态代理类在运行期动态生成

  • 一个真实角色必须对应一个静态代理角色,而动态代理大大减少了代理类的数量(一个动态代理对象多个真是角色)

  • 动态代理类不会作实质性的工作,在生成它的实例时必须提供一个handler,由它接管实际的工作(会自动执行handler的invoke方法)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值