代理模式的定义
达到某个目标,通过代理或自己直接去做,都可以完成,但是通过代理可以给自己代理某种好处,比如:租房找中间可以节省时间找到自己满意的房子;购票找黄牛可以解决春节一票难求的窘境;
代理模式的分类
静态代理
代理类的代码都是提前写好的
/**
* @author freedom
*/
public interface Buy {
/**
* 购买接口
*/
void buy();
}
/**
* @author : freedom
* @Description : 真正要买票的类
* @Creation Date: 2019-10-27 9:59 下午
*/
public class BuyTrainTicket implements Buy {
@Override
public void buy() {
System.out.println("我要购买一张从北京到上海的高铁票");
}
}
/**
* @author : freedom
* @Description : 代理买票的黄牛类
* @Creation Date: 2019-10-27 10:03 下午
*/
public class BuyTrainTicketProxy implements Buy {
private Buy buyTrainTicket;
BuyTrainTicketProxy(Buy buy) {
this.buyTrainTicket = buy;
}
@Override
public void buy() {
System.out.println("我帮你抢从北京到上海的票");
System.out.println("我要收取50元的手续费");
buyTrainTicket.buy();
System.out.println("加个微信,下次买给你打八折");
}
}
/**
* @author : freedom
* @Description : 客户端测试类
* @Creation Date: 2019-10-27 10:08 下午
*/
public class StaticProxyTest {
public static void main(String[] args) {
Buy buyTrainTicket = new BuyTrainTicket();
BuyTrainTicketProxy buyTrainTicketProxy = new BuyTrainTicketProxy(buyTrainTicket);
buyTrainTicketProxy.buy();
}
}
运行结果:
我帮你抢从北京到上海的票
我要收取50元的手续费
我要购买一张从北京到上海的高铁票
加个微信,下次买给你打八折
动态代理
代理类的代码是通过java反射原理动态生成的
/**
* @author freedom
*/
public interface Buy {
/**
* 购买接口
*/
void buy();
}
package poxy;
/**
* @author : freedom
* @Description : 真正要买票的类
* @Creation Date: 2019-10-27 9:59 下午
*/
public class BuyTrainTicket implements Buy {
@Override
public void buy() {
System.out.println("我要购买一张从北京到上海的高铁票");
}
}
package poxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author : freedom
* @Description : 实现了InvocationHandler的代理处理器
* @Creation Date: 2019-10-28 6:50 上午
*/
public class DynamicTrainTicketHandler implements InvocationHandler {
private Buy buyTrainTicket;
DynamicTrainTicketHandler(Buy buy) {
this.buyTrainTicket = buy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我帮你抢从北京到上海的票");
System.out.println("我要收取50元的手续费");
//执行真正想实现目标对象的某个方法
method.invoke(buyTrainTicket, args);// java 反射 调用包装在当前Method对象中的方法。
System.out.println("加个微信,下次买给你打八折");
return null;
}
}
package poxy;
import java.lang.reflect.Proxy;
/**
* @author : freedom
* @Description : 动态代理客户端测试类
* @Creation Date: 2019-10-28 6:54 上午
*/
public class DynamicProxyTest {
public static void main(String[] args) {
//保存动态代理生成的源码位于当前项目的com.sun.proxy.$Proxy0.class 下
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//创建一个真正想达成目标的对象
Buy buyTrainTicket = new BuyTrainTicket();
//创建一个代理对象处理器
DynamicTrainTicketHandler dynamicTrainTicketHandler = new DynamicTrainTicketHandler(
buyTrainTicket);
//动态生成代理对象
Buy buy = (Buy) Proxy.newProxyInstance(buyTrainTicket.getClass().getClassLoader(),
buyTrainTicket.getClass().getInterfaces(), dynamicTrainTicketHandler);
//调用代理对象的购买动作方法
buy.buy();
}
}
运行结果:
我帮你抢从北京到上海的票
我要收取50元的手续费
我要购买一张从北京到上海的高铁票
加个微信,下次买给你打八折
动态生成的源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import poxy.Buy;
public final class $Proxy0 extends Proxy implements Buy {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $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 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 void buy() throws {
try {
//调用InvocationHandler.invoke方法
super.h.invoke(this, m3, (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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("poxy.Buy").getMethod("buy");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
代理模式的使用场景
缓存代理
将经常访问的数据放到内存中,作为缓存去使用,加快程序的访问处理速度,减轻数据存储被频繁访问的压力。
授权代理
对老旧的业务系统添加授权认证,为了解耦耦合,增加一个授权代理即可。
远程代理
远程服务器配置高,性能强劲,网络延迟低,处理能力强,可以将本地复杂的业务逻辑交于远程服务器处理,减少对客户端的响应时间
虚实代理
网络服务为了显示多张高分辨的图片,以及为了处理高负载运算,使用虚代理呈现给客户端,当客户端正在去看时,再调用真实的对象去处理。