zoukankan      html  css  js  c++  java
  • 设计模式-代理模式

    1. 代理模式的作用

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

    2. 代理模式的本质

      监控行为特征

    3. 案例

      (1)喝果粒果汁

        主要业务:喝果汁

        次要业务:喝前摇一摇

      (2)JDK代理模式实现

        接口:定义所有需要被监听行为

        接口实现类:农夫果粒,果粒橙

        通知类:实现次要业务,当前被拦截的主要业务与次要业务如何绑定执行

        代理对象

      示例:

      (1)创建接口

    /*
     * 
     * 只有需要被监控的行为才有资格
     * 在这里声明 
     * 
     */
    public interface DrinkService {
         public void drink();
    }

     (2)接口实现类

    public class Huiyuan implements DrinkService {
        @Override
        public void drink() {
            System.out.println("喝汇源果汁");
        }
    }
    public class Guolicheng implements DrinkService {
        @Override
        public void drink() {
            System.out.println("喝果粒橙");
        }
    }

     (3)通知类

    public class GuozhiInvocationHandler implements InvocationHandler {
    
        private DrinkService target;
    
        public GuozhiInvocationHandler(DrinkService target){
            this.target = target;
        }
    
    //    invoke方法:在被监控行为将要执行时,会被JVM拦截,被监控行为和行为实现方会被作为参数输送invoke
    //               这个被拦截方法是如何与当前次要业务方法绑定实现
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object returnValue = null;
    
            if("drink".equals(method.getName())){
                yaoyiyao();
               returnValue = method.invoke(target,args);
            }
    
            return returnValue;
        }
    
        private void yaoyiyao(){
            System.out.println("喝前摇一摇");
        }
    }

      (4)代理类

    public class ProxyFactory {
    
        public static DrinkService builder(Class clazz) throws IllegalAccessException, InstantiationException {
    
            //1.创建被监控实例对象
            DrinkService target = (DrinkService) clazz.newInstance();
            //2.创建一个通知对象
            InvocationHandler adviser = new GuozhiInvocationHandler(target);
            //3.向JVM申请负责监控target对象指定行为的监控对象(代理对象)
            /*
             *  loader:被监控对象隶属的类文件在内存中真实地址
             *  interfaces:被监控对象隶属的类文件实现接口
             *  h:监控对象发现小明要执行被监控行为,应该有哪一个通知对象进行辅助
             */
            DrinkService $proxy = (DrinkService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),adviser);
            return $proxy;
        }
    }

    测试类:

    public class TestDemo {
        public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    
            DrinkService huiyuan = ProxyFactory.builder(Huiyuan.class);
            huiyuan.drink();
            DrinkService guolicheng = ProxyFactory.builder(Guolicheng.class);
            guolicheng.drink();
        }
    }

    测试结果:

    喝前摇一摇
    喝汇源果汁
    喝前摇一摇
    喝果粒橙

  • 相关阅读:
    mq/mysql/redis/nginx常见服务&工具安装
    中断——中断描述符表的定义和初始化(二) (基于3.16-rc4)
    中断——中断描述符表的定义和初始化(一) (基于3.16-rc4)
    linux内核中与进程相关的数据结构(基于linux3.16-rc4)
    内核链表的应用
    ubuntu下做柯老师lab19-lab20实验问题总结
    在ns2.35中添加myevalvid框架
    在ns2.35下完成柯老师lab18实验
    windows编程socket问题
    如何高效利用GitHub
  • 原文地址:https://www.cnblogs.com/yintingting/p/6872740.html
Copyright © 2011-2022 走看看