• 设计模式之☞代理模式


    一、代理模式的作用

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

    二、代理模式本质

    • 监控行为的特征

    例子:

      <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 }

    吃饭

     上厕所

    项目目录结构

  • 相关阅读:
    为什么C++(感谢waterwalk翻译)
    容器操作笔记
    如此理解面向对象编程
    C++初学者小细节(不定时更新)
    Sales_item 专题
    10步让你成为更优秀的程序员
    C++ PRIMER 笔记
    C++ 异常处理
    透明度 rgba 和 opacity 的区别
    盒模型
  • 原文地址:https://www.cnblogs.com/chenyanbin/p/11674422.html
Copyright © 2020-2023  润新知