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

    代理模式(Proxy)

    定义

      为其他对象提供一种代理以控制对这个对象的访问。

    UML结构图

      

    例子

      一个人希望去追求一个女生,但是不好意思直接送礼物给女生,所以就只有找一个女生的朋友,代表他去送礼物,和女生直接接触的并不是该追求者,而是中间的代理对象。

    package com.csdhsm.designpattem.proxy;
    
    /**  
     * @Title:  GivenGift.java   
     * @Description: 定义一个公用的接口,也就是类图中的Subject
     * @author: Han   
     * @date:   2016年6月20日 下午3:43:42   
     */  
    public interface GivenGift {
        
        //送花
        public void giveFlower();
        
        //送书
        public void giveBook();
        
        //送钱
        public void giveMoney();
    }

      女生

    package com.csdhsm.designpattem.proxy;
    
    /**  
     * @Title:  SchoolGirl.java   
     * @Description: 女生类
     * @author: Han   
     * @date:   2016年6月20日 下午3:46:45   
     */  
    public class SchoolGirl {
        
        private String name;
        
        public SchoolGirl(String name) {
            this.name = name;
        }
        
        public String getName() {
            return name;
        }
    }

      追求者

    package com.csdhsm.designpattem.proxy;
    
    /**  
     * @Title:  Pursuit.java   
     * @Description: 追求者,但是不好意思直接给MM送礼物
     * @author: Han   
     * @date:   2016年6月20日 下午3:43:14   
     */  
    public class Pursuit implements GivenGift {
    
        private SchoolGirl mm;
        
        public Pursuit(SchoolGirl mm) {
            this.mm = mm;
        }
        
        @Override
        public void giveFlower() {
            System.out.println("给" + mm.getName() + "送花!");
        }
    
        @Override
        public void giveBook() {
            System.out.println("给" + mm.getName() + "送书!");
        }
    
        @Override
        public void giveMoney() {
            System.out.println("给" + mm.getName() + "送钱!");
        }
    }

      代替送礼物的人

    package com.csdhsm.designpattem.proxy;
    
    /**  
     * @Title:  Proxy.java   
     * @Description: 代理类,代替Pursuit去送东西
     * @author: Han   
     * @date:   2016年6月20日 下午3:42:51   
     */  
    public class Proxy implements GivenGift {
    
        private Pursuit pursuit;
        
        public Proxy(SchoolGirl mm) {
            if(pursuit == null) {
                pursuit = new Pursuit(mm);
            } 
        }
        
        @Override
        public void giveFlower() {
            pursuit.giveFlower();
        }
    
        @Override
        public void giveBook() {
            pursuit.giveBook();
        }
    
        @Override
        public void giveMoney() {
            pursuit.giveMoney();
        }
    }

      客户端

    package com.csdhsm.designpattem.proxy;
    
    public class Solution {
        
        public static void main(String[] args) {
            SchoolGirl mm = new SchoolGirl("小美");
            Proxy proxy = new Proxy(mm);
            
            proxy.giveBook();
            proxy.giveFlower();
            proxy.giveMoney();
        }
    }

      OK,代理模式成功。

    动态代理

      上面的代理属于静态代理,前段时间再看AOP,研究了下动态代理,记录下来,方便以后回忆。

      动态代理:在程序运行时,运用反射机制动态创建而成。

    动态代理例子

    package com.csdhsm.dynamicproxy;
    
    /**  
     * @Title:  Subject.java   
     * @Description: 一个会跑,会打招呼的接口
     * @author: Han   
     * @date:   2016年6月20日 下午4:08:11   
     */  
    public interface Subject {
        
        public void run();
        
        public void hello(String str);
    }
    package com.csdhsm.dynamicproxy;
    
    /**  
     * @Title:  RealSubject.java   
     * @Description: 真实的对象类
     * @author: Han   
     * @date:   2016年6月20日 下午4:10:04   
     */  
    public class RealSubject implements Subject {
    
        @Override
        public void run() {
            System.out.println("I`m running");
        }
    
        @Override
        public void hello(String str) {
            System.out.println("say hello to " + str);
        }
    }

      上面的两个对象一个是Subject接口,一个是RealSubject,接下来是代理对象。

    package com.csdhsm.dynamicproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**  
     * @Title:  DynamicProxy.java   
     * @Description: 动态代理类
     * @author: Han   
     * @date:   2016年6月20日 下午4:10:35   
     */  
    public class DynamicProxy implements InvocationHandler {
    
        private Object subject;
        
        public DynamicProxy(Object subject) {
            this.subject = subject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            System.out.println("before-----------------");
            method.invoke(subject, args);
            System.out.println("after------------------");
            return null;
        }
    }

      想要成为动态代理类,就需要实现InvocationHandler接口,该接口只有一个方法,就是invoke方法,打开API文档。

      该方法是在代理实例上处理相关联的方法的时候调用该方法,我的理解是,在调用关联方法时,用该方法代替,也就是这个方法代理了原方法。

      proxy参数,表示实现方法的代理实例。

      method代理方法,用反射实现该方法。

      args该方法的参数。

      说明:很多同学会有疑问 method.invoke(subject, args); 这句是否可以写成 method.invoke(proxy, args); ,很明显是不可以的,因为proxy是代理对象实例,这样的结果会是

      很明显就是一直在调用相同的方法,陷入死循环中。

      

      客户端

    package com.csdhsm.dynamicproxy;
    
    import java.lang.reflect.Proxy;
    
    public class Solution {
        
        public static void main(String[] args) {
            
            Subject subject = new RealSubject();
            DynamicProxy proxy = new DynamicProxy(subject);
            //获取该代理对象
            Subject realSubject = (Subject)Proxy.newProxyInstance(proxy.getClass().getClassLoader(),
                    subject.getClass().getInterfaces(), proxy);
            
            realSubject.run();
            realSubject.hello("Jack");
        }
    }

      重点在与这个方法Proxy.newProxyInstance(),贴出API

      这个方法返回一个代理实例,其中:

      loader代理对象类加载器

      interfaces接口列表,其中就是关联的方法

      h代理对象

    结果

      OK,成功!

  • 相关阅读:
    详解Codis安装与部署
    停车场地图开发
    dlib换脸
    海康相机官网硬触发设置
    python操作数据库
    心率和血氧测量
    音乐模块
    flask网页显示图片
    树莓派识别二维码
    树莓派python获取自身IP
  • 原文地址:https://www.cnblogs.com/a294098789/p/5601089.html
Copyright © 2011-2022 走看看