• 设计模式(三)—代理模式


    目录:

    一、概述

    二、静态代理

    三、动态代理

    四、静态代理和动态代理的区别

    一、概述

         代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因 为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。先来看看关系图:

                image

    二、静态代理

    Sourceable.java

    public interface Sourceable{
    
    	public void method();
    }

    Source.java

    public class Source implements Sourceable{
    
    	@Override
    	public void method(){
    		System.out.println("原生的方法...");
    	}
    
    }

    Proxy.java

    public class Proxy implements Sourceable{
    
    	private Source source;
    	
    	public Proxy(){
    		this.source = new Source();
    	}
    	
    	@Override
    	public void method(){
    		
    		before();
    		source.method();
    		after();
    		
    	}
    
    	private void after(){
    		System.out.println("方法执行之前....");	
    	}
    
    	private void before(){
    		System.out.println("方法执行之后.....");
    	}
    
    }

    测试:

    	@Test
    	public void testProxy(){
    		Sourceable source = new Proxy();
    		source.method();
    	}

    结果:

          方法执行之后.....
          原生的方法...
          方法执行之前....

    代理模式的应用场景:
    如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
    (1)修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。
    (2)就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
    使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

    你会发现每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类

    所以我们就会想办法可以通过一个代理类完成全部的代理功能,那么我们就需要用动态代理。

    三、动态代理

    public class InvocationHandlerImpl implements InvocationHandler{
    	
    	private Object target;
    	
    	public InvocationHandlerImpl(Object target){
    		this.target = target;
    	}
    	
    	/*
         * proxy: 正在返回的那个代理对象,一般情况下,在invoke方法中都不使用
         * method: 正在被调用的方法
         * args:调用方法时传入的参数
         */
    	@Override
    	public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
    		System.out.println("target : " + target.getClass().getName());
    		System.out.println("proxy : " + proxy.getClass().getName());
    		System.out.println("method : " + method.getName());
    		System.out.println("args : " + args);
    		
    		System.out.println("方法执行之前...");
    		Object obj = method.invoke(target, args);
    		System.out.println("方法执行之后...");
    		
    		return obj;
    	}
    
    }

    测试:

    	@Test
    	public void testProxy(){
    		Sourceable source = new Source();
    		
    		//获取代理对象
    		Sourceable sourceProxy = (Sourceable)Proxy.newProxyInstance(
    							source.getClass().getClassLoader(),
    							source.getClass().getInterfaces(),
    							new InvocationHandlerImpl(source));
    		
    		//通过代理调用方法
    		sourceProxy.method();
    	}

    结果:

          target : com.kiwi.p3.Source
          proxy : com.sun.proxy.$Proxy4
          method : method
          args : null
          方法执行之前...
          原生的方法...
          方法执行之后...

    四、静态代理与动态代理的区别

    (1)静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。 
    (2)静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。 
    (3)动态代理是实现JDK里的InvocationHandler接口的invoke方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过Proxy里的newProxyInstance得到代理对象。 还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。

  • 相关阅读:
    CronJob控制器中的一些绕坑指南
    Redis16个常见使用场景
    golang md5加密和python md5加密比较
    pyton Pillow 把透明背景转成白色背景的方法替换指定背景图片
    golang 语言中常见占位符含义 %s %d %c
    Java 获取图片rgb值 像素矩阵方法
    nginx 配置文件下载 文件下载器
    vue element 动态增加表单并进行表单验证
    浏览器返回的json自动格式化的插件
    springboot 增加跨域配置 解决前端跨域问题
  • 原文地址:https://www.cnblogs.com/yangang2013/p/5727013.html
Copyright © 2020-2023  润新知