代理模式

代理模式

1.定义

  • 代理模式,为其他对象提供一种代理以控制对这个对象的访问。
  • 代理对象在客户端和目标对象之间起到中介作用。属于结构型设计模式。
package cn.sun.code.seven;

/**
 * Subject类,定义了RealSubject和Proxy的公共接口,这样就在任何使用RealSubject的地方都可以
 * 使用Proxy
 */
interface Subject {

	void request();

}

/**
 * RealSubject类,定义Proxy所代表的真实实体
 */
class RealSubject implements Subject {

	@Override
	public void request() {
		System.out.println("真实的请求");
	}
}

/**
 * Proxy类,保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口
 * 这样代理就可以用来代替实体
 */
public class Proxy implements Subject {

	private RealSubject realSubject;

	@Override
	public void request() {
		// 可以在这里给被代理对象定制一些特性
		if (realSubject == null) {
			realSubject = new RealSubject();
		}
		System.out.println("对委托类开始增强");
		realSubject.request();
		System.out.println("对委托类增强结束");
	}

}

/**
 * 客户端代码
 */
class Client {

	public static void main(String[] args) {
		Proxy proxy = new Proxy();
		proxy.request();
	}

}

2.为什么使用代理模式

  • 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

3.静态代理

  • 静态代理在使用时,需要定义接口或者父类,被代理对象与与代理对象一起实现相同的接口或者是继承相同父类。

    • 定义中的示例即为标准静态代理方式。
    • 关键,在编译期确定代理对象,在程序运行前代理类的.class文件就已经存在。
  • 静态代理的缺陷:

    • 每个代理类都必须实现一遍委托类(realSubject)的接口,如果接口增加方法,则代理类也必须跟着修改。增加了代码维护的复杂度。

4.动态代理

  • 动态代理是根据代理的对象,动态创建代理类。
  • 动态代理是通过反射实现的,可以借助Java自带的java.lang.reflect.Proxy实现
    1. 编写一个委托类的接口,即静态代理中的Subject接口
    2. 实现一个委托类,即静态代理中的RealSubject类
    3. 创建一个动态代理类,实现InvocationHandler接口,并重写该invoke()方法
    4. 在客户端中,生成动态代理对象
package cn.sun.code.seven;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理类
 */
public class DynamicProxy implements InvocationHandler {

	private Object object;

	public DynamicProxy(Object object) {
		this.object = object;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("对委托类开始增强");
		Object invoke = method.invoke(object, args);
		System.out.println("对委托类增强结束");
		return invoke;
	}

}

/**
 * 客户端对象
 */
class Client2 {

	public static void main(String[] args) {
		Subject realSubject = new RealSubject();
		DynamicProxy proxy = new DynamicProxy(realSubject);
		ClassLoader classLoader = realSubject.getClass().getClassLoader();
		Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy);
		subject.request();
	}
}

  • InvocationHandler接口说明

      /**
       * {@code InvocationHandler} is the interface implemented by
       * the <i>invocation handler</i> of a proxy instance.
       *
       * <p>Each proxy instance has an associated invocation handler.
       * When a method is invoked on a proxy instance, the method
       * invocation is encoded and dispatched to the {@code invoke}
       * method of its invocation handler.
       *
       */
    
    • 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

    • invoke()方法

      •     public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable;
        // proxy:指我们所代理的那个真实对象
        // method:指我们所要调用真实对象的某个方法的method对象
        // args:指调用真实方法某个对象时所接受的参数
        

  • Proxy类说明

    • Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods. 
      
    • Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多静态方法,但是我们用的最多的就是newProxyInstance()这个方法:

      • public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException
        
        • loader:一个ClassLoader对象,定义由哪个ClassLoader对象来对生成的代理对象进行加载
        • interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口,这样生成的代理类就能调用这组接口中的方法了
        • h:一个InvocationHandler对象,表示的是当这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
原文地址:https://www.cnblogs.com/riders/p/12660783.html