设计模式之代理模式

代理模式分为静态代理和动态代理

静态代理

就拿网络请求来说
先定义一个网络请求统一接口INetworkRequester 里面有一个post方法

public interface INetworkRequester{
	void post();
}

网络请求框架有很多种比如早期的 Volley 现在的Okhttp

public class OkhttpNetworkRequester implements INetworkRequester{
	public void post(){
		Log.i("ancely_proxy","OkhttpNetworkRequester.post()");
	}
}

public class VolleyNetworkRequester implements INetworkRequester{
	public void post(){
		Log.i("ancely_proxy","VolleyNetworkRequester.post()");
	}
}

在请求网络的时候有一个代理的网络请求器,在请求网络的时候我们并不关心里面是怎么请求的,只要能达到目的就可以

public class ProxyNetworkRequester implements INetworkRequester{
	private INetworkRequester mRequester;
	public ProxyNetworkRequester(INetworkRequester requester){
		mRequester = requester;
	}
	public void post(){
		mRequester.post();
	}

}

假如我们一开始使用的是Volley请求库,我们只需要这样调用

INetworkRequester requester = new ProxyNetworkRequester(new VolleyNetworkRequester());
requester.post();//这样用的就是Volley框架

//后面更新迭代,Volley不受欢迎,Okhttp流行起来了我们要换库就非常的方便
INetworkRequester requester = new ProxyNetworkRequester(new OkhttpNetworkRequester());
requester.post();//这样用的就是Okhttp框架

当然比如常用的Json序列化库也可以同样操作

动态代理

动态代理使用起来其实很简单,主要是调用Proxy的newProxyInstance方法

INetworkRequester requester = new ProxyNetworkRequester(new VolleyNetworkRequester());
Object proxyInstance = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{INetworkRequester.class}, (o, method, objects) -> {
    Log.i("ancely_proxy","newProxyInstance.post()");
    return method.invoke(requester,objects);
});
INetworkRequester requester1 = (INetworkRequester) proxyInstance;
Log.i("ancely_proxy","proxyInstance hashCode: ."+ requester1.hashCode());
requester1.post();

动态代理原理

  • 类的完整生命周期
    Java源文件---->编译生成java字解码.class文件(实实在在的文件)---->通过类加载机制变成Class对象----->然后再实例化出对象—>卸载

  • 动态代理的class对象是怎么来的

    • 逻辑在Proxy的newProxyInstance里
    • 通过Proxy里的getProxyClass0方法创建了一个Class对象cl,怎么生成的我们不关心
    • 获取Class对象的构造方法cl.getConstructor(constructorParams);
    • 反射创建对象cons.newInstance(h);h就是我们newProxyInstance方法里传进定数的InvocationHandler接口
      源码如下
private static final Class<?>[] constructorParams = new Class[]{InvocationHandler.class};
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) {
        Objects.requireNonNull(h);
        final Class<?>[] intfs = interfaces.clone();
        //创建了一个Class对象
        Class<?> cl = getProxyClass0(loader, intfs);
        try {
        		//获取到构造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                cons.setAccessible(true);
            }
            //通过构造方法实例出对象,
            return cons.newInstance(h);
        } catch (Exception e) {
            throw new InternalError(e.toString(), e);
        } 
    }

内存中生成的Class是什么样的,通过以下方法可以获取

String name = INetworkRequester.class.getName() + "$Proxy0";
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{INetworkRequester.class});
try {
    FileOutputStream fos = new FileOutputStream("complier/" + name + ".class");
    fos.write(bytes);
    fos.close();
} catch (Exception e) {
    e.printStackTrace();
}
package com.ancely.complier;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class INetworkRequester$Proxy0 extends Proxy implements INetworkRequester {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;
    public INetworkRequester$Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
    public final void post() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.ancely.complier.INetworkRequester").getMethod("post");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

通过上面文件就非常清楚动态代理的原理了

  • 1.通过Proxy.newProxyInstance创建了一个Object对象 proxyObject
  • 2.通过生成的文件可以发现 proxyObject是继承了Proxy 实现了代理接口INetworkRequester
  • 3.在生成的Class文件的构造方法中传入了我们在newProxyInstance方法中传入了InvocationHandler参数,
  • 4.所以生成的Class文件执有了一个InvocationHandler h
  • 5.当我们调用了proxyObject对应的方法时就会调用InvocationHandler h的invoke方法
代理模式是一种结构型设计模式,它提供一个代理对象来代表另一个对象。在代理模式中,有一个被称为实际对象(Subject)和一个被称为代理对象(Proxy)的中介,代理对象持有实际对象的引用,并且可以控制对实际对象的访问。代理模式的主要目的是在不修改原始对象的情况下,为原始对象添加额外的逻辑处理。 代理模式分为多种类型,如远程代理、虚拟代理、保护代理等,它们各自有不同的应用场景: - 远程代理:为远程对象提供一个本地代表。 - 虚拟代理:根据需要创建开销大的对象,通过虚拟代理控制访问这些对象的过程。 - 保护代理:控制对原始对象的访问权限,例如进行权限检查。 代理模式的优点包括: 1. 能够控制对真实对象的访问,并在访问前后添加额外的逻辑。 2. 可以通过代理对象实现延迟加载,即在实际需要时才创建真实对象。 3. 增强了对真实对象的封装,并且可以避免对真实对象的重复引用。 在C#中实现代理模式通常涉及以下步骤: 1. 定义一个接口或抽象类,声明真实对象和代理对象需要实现的方法。 2. 实现真实对象的类,按照接口或抽象类的要求实现具体方法。 3. 实现代理类,它同样实现接口或抽象类,并在方法中持有真实对象的引用,通过调用真实对象的方法来执行所需的操作,同时可以添加额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值