在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外提供功能接口
意图:为其他对象提供一种代理以控制对这个对象的访问 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销大,或者某些操作需要安全控制,或者需要进程外的范文),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制
如何解决:增加中间层
抽象角色:一般会使用接口或抽象类来解决 真实角色:被代理的角色 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作 客户:访问代理对象的人
以找中介租房子为例
租房接口
package GProxy.stactic; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 14:03 * 租房 */ public interface Rent { public void rent(); }房东出租房屋
package GProxy.stactic; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 14:03 * 房东 */ public class Host implements Rent { @Override public void rent() { System.out.println("房东要出租房子"); } }中介
package GProxy.stactic; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 14:04 中介角色: */ public class Proxy implements Rent { //将房东组合进来 private Host host; public Proxy(Host host) { this.host = host; } //看房 public void seeHouse(){ System.out.println("中介带你看房"); } public void fare(){ System.out.println("收中介非"); } @Override public void rent() { seeHouse(); host.rent(); fare(); } }优点
可以使得真实角色的操作更加纯粹!不用关注一些公共的业务公共也就交给代理角色,实现业务的分工公共业务发生扩展的时候,方便集中管理相关的类与接口 Proxy InvocationHandler
Proxy类
//通过这个方法返回被代理的对象 @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)InvocationHandler接口
//在InvocationHandler中进行方法的增强 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;租赁接口
package GProxy.dynamic; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 14:03 * 租房 */ public interface Rent { public void rent(); } package GProxy.dynamic; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 14:03 * 房东 */ public class Host implements Rent { @Override public void rent() { System.out.println("房东要出租房子"); } }增强的对象
package GProxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 15:53 */ public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Rent rent; public ProxyInvocationHandler(Rent rent) { this.rent = rent; } public ProxyInvocationHandler() { } public Rent getRent() { return rent; } public void setRent(Rent rent) { this.rent = rent; } //生成得到的代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this); } //处理代理实例,并放回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //动态代理的本质:就是使用反射机制实现 System.out.println("看房子"); Object result = method.invoke(rent,args); return result; } }客户端调用
package GProxy.dynamic; import com.sun.org.apache.regexp.internal.RE; /** * @Author Zhou jian * @Date 2020 ${month} 2020/7/2 0002 15:57 */ public class Client { public static void main(String[] args) { //真实角色 Host host = new Host(); //代理角色 ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(); //通过调用程序处理角色来处理我们要调用的街路口对象 proxyInvocationHandler.setRent(host); Rent proxy = (Rent)proxyInvocationHandler.getProxy();//这里的proxy就是通过动态代理生成的,我们并没有写 proxy.rent(); } }