设计模式之☞代理模式

  • 2019 年 10 月 14 日
  • 笔记

一、代理模式的作用

  • 将主要业务与次要业务进行松耦合的组装

二、代理模式本质

  • 监控行为的特征

例子:

  <input type=”button” onclick=”处理函数”>

三、生活案例

案例:饭前便后要洗手

分析:

  1.分析出主要业务和次要业务

  【主要业务】:吃饭,上厕所

  【次要业务】:洗手

  2.JDK代理模式实现

    2.1、接口角色:定义所有需要被监听行为

BaseService.java

1 package com.chenyanbin.service;  2  3 /*  4  * 只有需要被监控的行为才有资格在这里声明  5  */  6 public interface BaseService {  7     public void Eat();  8     public void Wc();  9 }

    2.2、接口实现类:中国人、印度人

Person.java

 1 package com.chenyanbin.serviceImpl;   2   3 import com.chenyanbin.service.BaseService;   4   5 public class Person implements BaseService {   6   7     @Override   8     public void Eat() { //主要业务,代理模式要求开发任务只关心主要业务   9         System.out.println("使用筷子吃饭");  10     }  11  12     @Override  13     public void Wc() {  14         System.out.println("测试地球重力是否存在");  15     }  16 }

    2.3、通知类:1)次要业务进行具体实现    2)通知JVM,当前被拦截的主要业务方法与次要业务方法应该如何绑定执行

Invaction.java

 1 package com.chenyanbin.util;   2   3 import java.lang.reflect.InvocationHandler;   4 import java.lang.reflect.Method;   5   6 import com.chenyanbin.service.BaseService;   7   8 public class Invaction implements InvocationHandler {   9     private BaseService obj;// 具体被监控对象  10  11     public Invaction(BaseService param) {  12         this.obj = param;  13     }  14  15     /*  16      * invoke方法:被监控行为将要执行时,会被JVM拦截,被监控行为和行为实现方会被作为参数输送到invoke  17      * ***通知JVM,这个被拦截方法是如何与当前次要业务方法绑定实现 invoke方法三个参数 小明.Eat();//JVM拦截  18      * Eat方法封装为Method类型方法 Eat方法运行时所有的实参封装到Object[] 将负责监控小明的代理对象作为invoke方法第一个参数  19      *  20      */  21     @Override  22     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  23         // 0.局部变量,接受主要业务方法执行完毕后返回值  24         Object value;  25         // 1.确认当前被拦截行为  26         String methodName = method.getName();  27         // 2.根据被拦截行为不同,决定主要业务和次要业务如何绑定执行  28         if ("Eat".equals(methodName)) { // 饭前要洗手  29             Wash();// 洗手  30             value = method.invoke(this.obj, args);// 当前主要业务  31         } else { // 便后洗手  32             value = method.invoke(this.obj, args);// 当前主要业务  33             Wash();// 洗手  34         }  35         return value; //返回被拦截方法  36     }  37  38     // 次要业务  39     public void Wash() {  40         System.out.println("--------洗手--------");  41     }  42 }

    2.4、监控对象(代理对象):1)被监控实例对象   2)需要被监控行为   3)具体通知类实例对象

ProxyFactory.java

 1 package com.chenyanbin.util;   2   3 import java.lang.reflect.InvocationHandler;   4 import java.lang.reflect.Proxy;   5   6 import com.chenyanbin.service.BaseService;   7   8 public class ProxyFactory {   9     /*  10      * JDK动态代理模式下,代理对象的数据类型 应该由监控行为来描述 参数:Class文件,监控类  11      */  12     public static BaseService build(Class classFile) throws Exception {  13         //1.创建被监控实例对象  14         BaseService obj = (BaseService) classFile.getDeclaredConstructor().newInstance();  15         //2.创建通知对象  16         InvocationHandler adviser=new Invaction(obj);  17         //3.向JVM申请负责监控obj对象指定行为的监控对象(代理对象)  18         /*  19          * loader:被监控对象隶属的类文件在内存中真实地址  20          * interfaces:被监控对象隶属的类文件实现接口  21          * h:监控对象发现小明要执行被监控行为,应该由哪一个通知对象进行辅助  22          */  23         BaseService $proxy=(BaseService)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), adviser);  24         return $proxy;  25     }  26 }

测试类

TestMain.java

 1 import com.chenyanbin.service.BaseService;   2 import com.chenyanbin.serviceImpl.Person;   3 import com.chenyanbin.util.ProxyFactory;   4   5 public class TestMain {   6   7     public static void main(String[] args) throws Exception {   8         //mike.Eat();   9 //        Person mike=new Person();  10         BaseService mike = ProxyFactory.build(Person.class);  11         mike.Eat();  12     }  13 }

吃饭

 

 上厕所

项目目录结构