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

    目录:

    一、概述

    二、静态代理

    三、动态代理

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

    一、概述

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

                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,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。

  • 相关阅读:
    Atitit sql计划任务与查询优化器统计信息模块
    Atitit  数据库的事件机制触发器与定时任务attilax总结
    Atitit 图像处理知识点体系知识图谱 路线图attilax总结 v4 qcb.xlsx
    Atitit 图像处理 深刻理解梯度原理计算.v1 qc8
    Atiti 数据库系统原理 与数据库方面的书籍 attilax总结 v3 .docx
    Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析
    Atitit View事件分发机制
    Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结
    Atitti 存储引擎支持的国内点与特性attilax总结
    Atitit 深入理解软件的本质 attilax总结 软件三原则"三次原则"是DRY原则和YAGNI原则的折
  • 原文地址:https://www.cnblogs.com/yangang2013/p/5727013.html
Copyright © 2011-2022 走看看