设计模式(四)---- 代理模式
代理模式(Proxy Pattern)
核心作用:通过代理控制对象的访问;可以详细访问某个类或对象的方法,在调用这个方法之前做前置处理,调用这个方法之后做后置处理;(AOP的微实现)
核心角色:
(1)抽象角色:定义代理角色和真实角色的公共对外方法;
(2)真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用;(关注真正的业务逻辑)
(3)代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法并附加自己的操作;将统一的流程控制放到代理角色中处理。
应用场景:
安全代理:屏蔽堆真实角色的直接访问;
远程代理:通过代理类处理远程方法调用(RMI);
延时加载:先加载轻量级的代理对象,真正需要时在加载真实对象。
分类:
静态代理(静态定义代理类)
动态代理(动态生成代理类)
JDK自带的动态代理;
java assist 字节码操作实现;
CGLIB
ASM(底层使用指令,可维护性较差)
一、静态代理模式
抽象角色:
public interface Star { void confer(); //面谈 void signContract();//签合同 void bookTicket(); //订票 void sing(); //唱歌 void collectMoney();//收钱 }
真实角色:
public class RealStar implements Star { @Override public void confer() { System.out.println("RealStar.confer()"); } @Override public void signContract() { System.out.println("RealStar.signContract()"); } @Override public void bookTicket() { System.out.println("RealStar.bookTicket()"); } @Override public void sing() { System.out.println("RealStar.sing(周杰伦)"); } @Override public void collectMoney() { System.out.println("RealStar.collectMoney()"); } }
代理角色:
public class ProxyStar implements Star { private Star star; public ProxyStar(Star star) { this.star = star; } @Override public void confer() { System.out.println("ProxyStar.confer()"); } @Override public void signContract() { System.out.println("ProxyStar.signContract()"); } @Override public void bookTicket() { System.out.println("ProxyStar.bookTicket()"); } @Override public void sing() { star.sing(); } @Override public void collectMoney() { System.out.println("ProxyStar.collectMoney()"); } }
测试代码:
public class Test { public static void main(String[] args) { RealStar realStar = new RealStar(); Star star = new ProxyStar(realStar); star.confer(); star.signContract(); star.bookTicket(); star.sing(); // star.collectMoney(); } }
二、动态代理(Dynamic Proxy)
动态代理相比于静态代理的优点:
抽象角色(接口)中声明的所有方法都被转移到调用处理器一个集中的方法中,这样我们可以使用更加灵活统一的处理众多的方法。
1、JDK自带的类
(1)动态代理需要的处理
java.lang.reflect.InvocationHandler (处理器接口):可以通过 invoke 方法实现对真实对象的代理访问;每次通过Proxy生成的代理类对象时都有指定代理器对象。
java.lang.reflect.Proxy : 生成代理类和对象。
(2)代码实现:抽象角色、真实角色同上
代理角色:
public class ProxyStar implements InvocationHandler
{
private Star star;
public ProxyStar(Star star)
{
this.star = star;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
Object object = null;
System.out.println("签合同");
System.out.println("定机票");
if("sing".equals(method.getName())) //执行的方法名为sing时, 调用真实角色的sing方法
{
object = method.invoke(star, args);
}
System.out.println("最后的方法执行");
return object;
}
}
测试类代码:
public class Test
{
public static void main(String[] args)
{
Star realStar = new RealStar();
InvocationHandler invocationHandler = new ProxyStar(realStar);
//生成代理对象
Star proxy = (Star) Proxy.newProxyInstance(
RealStar.class.getClassLoader(), //ClassLoader.getSystemClassLoader(),
RealStar.class.getInterfaces(), //new Class[]{Star.class},
invocationHandler);
//只要调用了代理对象的任何一个方法都会进入 InvocationHandler 实现类的 invoke() 方法
proxy.sing();
}
}